Тип выражения msg.data
отличается от типа выражения &msg.data
, но значения идентичны. Поскольку это C++, поведение очень четко указано в : вызов memcpy
вызывает неявное преобразование обоих аргументов указателя в [const] void *
, а результат этого преобразования «указывает на начало места хранения, в котором находится объект, как если это наиболее производный объект (а не подобъект базового класса) ". (В C эффект один и тот же, но стандартное менее понятно из-за того, что вы так говорите - вы должны вместе прочитать параграфы 1 и 7 раздела C99 6.3.2.3 и понимать, что memcpy
ведет себя «как бы», он преобразует свои аргументы в указатели- к характеру-типа внутренне.)
data
объявлен как
unsigned char data[100];
поэтому все следующие условия эквивалентны и правильно. Первый из них был бы предпочтительным стилем в большинстве кодовых баз, над которыми я работал.
memcpy(msg2.data, msg1.data, sizeof msg1.data);
memcpy(msg2.data, msg1.data, 100);
memcpy(msg2.data, msg1.data, 100 * sizeof(unsigned char));
memcpy(&msg2.data, &msg1.data, sizeof msg1.data);
memcpy(&msg2.data, &msg1.data, 100);
memcpy(&msg2.data, &msg1.data, 100 * sizeof(unsigned char));
Однако
memcpy(msg2.data, msg1.data, 100 * sizeof(unsigned int));
НЕПРАВИЛЬНО; он копирует слишком много памяти.¹ Вот почему форма с sizeof
является предпочтительным стилем; сложнее ошибиться в первом месте и не станет ошибочным, если изменение типа изменилось. ²
Также в качестве стиля я предпочитаю не писать &
в этом контексте, потому что &[anything with an array type]
почти всегда неправильно, поэтому его не следует писать таким образом, если это действительно не необходимо.
И вы должны знать, что sizeof(any sort of char) == 1
по определению (C++ [expr.sizeof]/1). Мое личное, но широко распространенное мнение, что это означает, что sizeof(char)
никогда не должно появляться в вашем коде.
И наконец, я не могу сказать вам правильный способ скопировать data2
без дополнительной информации. Мне нужно знать, что указывает data2
, как оно распределено, и следует ли его копировать или ссылаться.
¹ за исключением очень маловероятном случае, sizeof(unsigned char) == sizeof(unsigned int)
; это было верно в оригинальном Cray, и стандарты по-прежнему допускают возможность, но AFAIK ни один разработчик на самом деле не сделал этого за многие годы.
² Контраргумент: применяется sizeof
к типу массива, что является рискованным, потому что типы массивов «распадаются» на типы указателей, если им предоставлена малейшая возможность сделать это, поэтому снова было бы неправильно неправильно. В случае, если вы находитесь, хотя - копирование элементов структуры вручную - я думаю, что это менее опасно, чем альтернатива.
напоминание: 'memcpy' будет копировать * указатель *' data2' ** не ** данные, что 'data2' указывает на. –
Почему вы просто не используете 'sizeof msg2.data' для определения размера? Тем не менее, 'msg2 = msg1' также будет работать, чтобы скопировать структуру. Кроме того, использование 'memcpy()' для копирования чего-либо в большинстве случаев является неправильным, поэтому не используйте его вообще! Например. для массивов фиксированного размера вы должны использовать C++ 'std :: array', который позволяет выполнять простые назначения. Даже без этого использование 'std :: copy' было бы намного чище и безопаснее. –
Я согласен с использованием 'std :: copy'. Вероятно, он использует 'memcpy' внутри вашей реализации, и абстракция поможет вам предотвратить ошибки. – KABoissonneault