这个问题是对在不实际指向字符数组的情况下,给“char *”指针添加内容是否未定义行为?的后续提问。
在CWG 1314中,CWG确认在标准布局对象内使用无符号字符指针进行指针运算是合法的。这似乎意味着与链接问题中类似的一些代码应该按预期工作。
(为了更清晰,我已将
我很难相信委员会有意打破这个非常常见的习惯用法,使得所有C++17之前使用
在CWG 1314中,CWG确认在标准布局对象内使用无符号字符指针进行指针运算是合法的。这似乎意味着与链接问题中类似的一些代码应该按预期工作。
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中的新变化似乎意味着,除非在两个reinterpret_cast
之后使用std::launder
,否则此代码现在是未定义行为。在两个指针类型之间进行reinterpret_cast
的结果等同于两个static_cast
:第一个转换为cv void*
,第二个转换为目标指针类型。但是[expr.static.cast]/13暗示这会产生指向原始对象的指针,而不是指向目标类型对象的指针,因为Foo
类型的对象与其第一个字节处的unsigned char
对象不可互相转换,f.z
的第一个字节处的unsigned char
对象也不可与f.z
本身互相转换。我很难相信委员会有意打破这个非常常见的习惯用法,使得所有C++17之前使用
offsetof
的用法都变得未定义。
std::launder
与此无关。 - Brian Bip
不再指向Foo
。 它现在指向一个字节。 当您对字节数组指针执行指针算术运算时,它停止指向Foo
。 - Nicol Bolas