Ответ 1
Стандарт C вполне понятен. Эффективным типом объекта, названным p
, является void*
, потому что он имеет объявленный тип, см. 6.5/6
. Правила сглаживания в C99 применяются к чтению и записи, а запись в void*
через unsigned
lvalue в (1)
- это поведение undefined в соответствии с 6.5/7
.
В отличие от memcpy
of (2)
отлично, потому что unsigned char*
может псевдоним любого объекта (6.5/7
). Стандарт определяет memcpy
в 7.21.2/1
как
Для всех функций в этом подпункте каждый символ должен интерпретироваться так, как если бы он имел тип unsigned char (и, следовательно, все возможные представления объекта действительны и имеют другое значение).
Функция memcpy копирует n символов из объекта, на который указывает s2, в объект, на который указывает s1. Если копирование происходит между перекрывающимися объектами, поведение не определено.
Однако, если после этого существует использование p
, это может привести к поведению undefined в зависимости от битпаттерна. Если такого использования не происходит, этот код в порядке. C.
В соответствии с Стандартом С++, который, на мой взгляд, далеко не ясен в этом вопросе, я считаю, что следующее. Пожалуйста, не принимайте эту интерпретацию как единственно возможную - неопределенная/неполная спецификация оставляет много места для спекуляций.
Строка (1)
проблематична, поскольку выравнивание &p
может быть не подходит для типа unsigned
. Он изменяет тип объекта, хранящегося в p
, на unsigned int
. До тех пор, пока вы не получите доступ к этому объекту позже через p
, правила сглаживания не будут нарушены, но требования по выравниванию все равно могут быть.
Строка (2)
, однако, не имеет проблем с выравниванием и, следовательно, действительна, если вы не получаете доступ к p
впоследствии как void*
, что может вызвать поведение undefined в зависимости от того, как void*
тип интерпретирует хранимый битпаттерн. Я не думаю, что тип объекта изменяется таким образом.
Существует длинный GCC Bugreport, в котором также обсуждаются последствия записи через указатель, полученный в результате такого приведения, и какая разница Размещение - новое (люди в этом списке не согласны с тем, что это такое).