Этот вопрос является продолжением: Добавляет ли UB указатель "char *", когда он на самом деле не указывает на массив символов?
В CWG 1314 , CWG подтвердила, что допустимо выполнять арифметику указателей в объекте стандартной компоновки с использованием указателя unsigned char
.Это может означать, что некоторый код, подобный коду в связанном вопросе, должен работать как задумано:
struct Foo {
float x, y, z;
};
Foo f;
unsigned char *p = reinterpret_cast<unsigned char*>(&f) + offsetof(Foo, z); // (*)
*reinterpret_cast<float*>(p) = 42.0f;
(я заменил char
на unsigned char
для большей ясности.)
Однако, похоже, что новые изменения в C ++ 17 подразумевают, что этот код теперь UB, если только std::launder
не используется после обоих reinterpret_cast
s.Результат reinterpret_cast
между двумя типами указателей эквивалентен двум static_cast
с: первый - cv void*
, второй - типу указателя назначения.Но [expr.static.cast] / 13 подразумевает, что это создает указатель на исходный объект, а не на объект типа назначения, так как объект типа Foo
не может быть преобразован в указатель с объектом unsigned char
вего первый байт, а также объект unsigned char
в первом байте f.z
, взаимозаменяемый указателем с самим f.z
.
Мне трудно поверить, что комитет намеревался внести изменения, которые бы это сломалиочень распространенная идиома, делающая все пре-C ++ 17 использования offsetof
неопределенными.