Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在标准布局对象内执行指针运算(例如,使用offsetof)时,是否需要使用std::launder?_C++_Language Lawyer_C++17_Offsetof - Fatal编程技术网

C++ 在标准布局对象内执行指针运算(例如,使用offsetof)时,是否需要使用std::launder?

C++ 在标准布局对象内执行指针运算(例如,使用offsetof)时,是否需要使用std::launder?,c++,language-lawyer,c++17,offsetof,C++,Language Lawyer,C++17,Offsetof,这个问题是对以下问题的后续行动: 年,CWG确认在标准布局对象内使用无符号字符指针执行指针算法是合法的。这似乎意味着一些类似于链接问题中的代码应按预期工作: struct Foo { float x, y, z; }; Foo f; unsigned char *p = reinterpret_cast<unsigned char*>(&f) + offsetof(Foo, z); // (*) *reinterpret_cast<float*>(p)

这个问题是对以下问题的后续行动:

年,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;
structfoo{
浮动x,y,z;
};
福福;
unsigned char*p=reinterpret_cast(&f)+offsetof(Foo,z);//(*)
*重新解释铸件(p)=42.0f;
(为了更加清晰,我将
char
替换为
unsigned char
。)

然而,C++17中的新变化似乎意味着该代码现在是UB,除非在这两个
重新解释后都使用
std::launder
。两种指针类型之间的
重新解释转换
的结果相当于两种
静态转换
s:第一种转换为cv
void*
,第二种转换为目标指针类型。但是[expr.static.cast]/13意味着这将生成指向原始对象的指针,而不是指向目标类型的对象,因为
Foo
类型的对象在其第一个字节处不可与
无符号字符
对象进行指针互换,位于
f.z
指针第一个字节的
无符号字符
对象也不能与
f.z
本身进行相互转换


我发现很难相信委员会打算做出改变,打破这个非常常见的习惯用法,使所有C++17之前的
offsetof
用法都未定义。

你的问题是:

在一个应用程序中执行指针算术时,是否需要使用std::launder 标准布局对象(例如,具有偏移)

没有

std::launder
在这种情况下不会改变任何东西,因此与所提供的示例无关(imo编辑launder排除问题或询问其他问题)

std::launder
通常仅在某些情况下需要(例如,由于const成员),在这些情况下,您以某种运行时方式(例如,通过放置新对象)更改(或创建)基础对象。助记符:对象是“脏的”,需要对其进行
std::launder
'


仅使用标准布局类型不会导致需要使用std::launder的情况。

@Artyer严格别名不是这里的问题。严格的别名规则在C++17之前就存在,与之无关。@Brian:“这会产生指向原始对象的指针”我们在这里讨论的是什么“原始对象”
p
不再指向
Foo
。它指向一个字节。当你在字节数组指针上执行指针算术时,它停止指向一个
Foo
。@Brian:但你引用了CWG1314,说的不是这样。C++17中的任何内容都没有改变这两个方面,因此不清楚您在算术方面关心什么。。CWG最近似乎没有讨论这个问题,但几年前的最新讨论似乎没有明确的方向。@t.C.所以CWG在2011年到2013年之间改变了主意?知道为什么吗?
size\t
应该表示对象的大小,可能不足以表示指针。您应该使用
uintpr\u t
intptr\u t
。从整数到指针类型的映射无论如何都是由实现定义的,因此您的代码是否会按预期运行是由实现定义的。无论如何,我看不出答案与这个问题有什么关系。在这个问题上没有积分类型的转换。@walnut这是一种矛盾的证明,但我想你是对的。我更新了答案。