Kri*_*son 5 c++ pointers casting language-lawyer c++17
当从套接字接收预期消息时,请考虑以下示例:
struct myData {
uint8_t type;
int value;
}
myData readFromSocket(int socketFD) {
myData data{};
ssize_t bytes = recv(socketFD, reinterpret_cast<char*>(&data), sizeof(myData), 0);
if(bytes == sizeof(myData))
return data;
return myData{};
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我不清楚行为是否定义良好。
根据cppreference.com 上的reintrpret_cast,该行为已明确定义以供检查,因为 char 的对齐不如 myData 严格,并且因为强制转换专门针对 char 指针。我不清楚检查是否仅限于读取或是否包括对强制转换指针的写入。
5)解释下:
任何对象指针类型 T1* 都可以转换为另一个对象指针类型 cv T2*。这与 static_cast<cv T2*>(static_cast<cv void*>(expression)) 完全相同(这意味着如果 T2 的对齐要求不比 T1 更严格,则指针的值不会更改,并且结果指针的转换返回到其原始类型会产生原始值)。无论如何,只有在类型别名规则允许的情况下,才可以安全地取消引用结果指针(见下文)
以及类型别名的第三点:
AliasedType 是 std::byte (C++17 起)、char 或 unsigned char:这允许将任何对象的对象表示形式检查为字节数组。
我已经测试了与上面类似的代码,没有任何问题,但是由于这一切都取决于编译器所做的优化,我发现很难给出可能失败的确切示例。
本文提到向另一个方向(即从char*到 )进行转换myData会出现未定义的行为,并建议使用memcpy()。我的假设是,由于类型别名规则未涵盖强制转换,因此得出了此结论。
然而,这个邮件线程令人怀疑memcpy(),根据标准,应该给出这样的保证(参见下面的引用),并且在没有阅读标准的情况下,我倾向于同意,因为它看起来像对 进行了相同的memcpy()转换recv()。
在 C++ 社区中,当前的想法是 memcpy 允许输入双关语,但 IIRC C++ 标准实际上甚至不清楚为什么会出现这种情况,并且在其当前的编写中可能实际上没有办法。
无论如何,如果有人对此有所了解并能提供一些线索,我将不胜感激。我对这个问题的兴趣更多是学术性的而不是实践性的。我用 c++17 标记了它,因为这就是我正在从事的工作,欢迎对其他标准的见解。
C++ 标准在[basic.lval]/p8中指定别名规则:
\n\n\n如果程序尝试通过以下类型之一以外的泛左值访问对象的存储值,则行为未定义:
\n
\n。。。
\n\xe2\x80\x94 一个char,unsigned char, 或std\xe2\x80\x8b::\xe2\x80\x8bbyte类型。
术语access在[defns.access]中指定:
\n\n\n\xe2\x9f\xa8execution-time action\xe2\x9f\xa9 读取或修改对象的值
\n
除此之外,没有其他规则表明别名是单向工作的。
\n所以我们可以得出结论,别名是双向的,并且代码是可以的。
\n但请注意,如果被覆盖的对象包含const成员,那么您应该std::launder在覆盖后添加成员,否则编译器可以假设const成员永远不会改变。