c++ - 修改 char 数组时,reintrepret_cast to char* 是否定义明确?

标签 c++ pointers casting c++17 language-lawyer

从套接字接收预期消息时考虑以下示例:

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{};
}

在这个例子中,我不清楚行为是否定义明确。

根据 reintrpret_cast on cppreference.com该行为已针对检查 进行了明确定义,因为 char 的对齐不如 myData 的对齐那么严格,并且因为强制转换专门针对 char 指针。我不清楚检查是否只针对读取,或者是否包括对已转换指针的写入。

5) 正在解释:

Any object pointer type T1* can be converted to another object pointer type cv T2*. This is exactly equivalent to static_cast<cv T2*>(static_cast<cv void*>(expression)) (which implies that if T2's alignment requirement is not stricter than T1's, the value of the pointer does not change and conversion of the resulting pointer back to its original type yields the original value). In any case, the resulting pointer may only be dereferenced safely if allowed by the type aliasing rules (see below)

还有第三点类型别名:

AliasedType is std::byte (since C++17), char, or unsigned char: this permits examination of the object representation of any object as an array of bytes.

我已经测试了与上面类似的代码,没有任何问题,但是由于这一切都归结为编译器做了哪些优化,我发现很难给出一个确切的例子来说明这可能会失败。

This article提到在另一个方向上进行转换,即从 char*myData 会出现未定义的行为,并建议使用 memcpy()。我的假设是得出这个结论是因为类型别名规则没有涵盖转换。

但是this mail thread怀疑 memcpy(),根据标准,应该提供这种保证(见下面的引用)并且在没有阅读标准的情况下我倾向于同意,因为它看起来像对memcpy()recv()

In the C++ community, the current thinking is that memcpy allows to type pun, but IIRC the C++ standard is actually not even clear as for why this is the case, and in its current writing it might be that there is actually no way.

无论如何,如果有人对此有所了解并且可以阐明一些信息,我将不胜感激。我对这件事的兴趣更多是学术上的,而不是实践上的。我用 c++17 标记了它,因为这是我正在从事的工作,欢迎对其他标准的见解。

最佳答案

C++ 标准在 [basic.lval]/p8 中指定了别名规则:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:
. . .
— a char, unsigned char, or std​::​byte type.

术语access[defns.access] 中指定:

⟨execution-time action⟩ to read or modify the value of an object

除此之外,没有其他规则表明别名是单向工作的。

因此我们可以得出结论,别名是双向工作的,代码没问题。

但是请注意,如果被覆盖的对象包含const成员,那么您应该在覆盖后std::launder它,否则允许编译器假设const 成员永远不会改变。

关于c++ - 修改 char 数组时,reintrepret_cast to char* 是否定义明确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63619444/

相关文章:

c++ - 内存没有被释放,导致巨大的内存泄漏

c - C 中指向无效位置错误的指针

c# - 在 C# 中转换泛型字典

c++ - 如何在 Visual Studio 2012 C++ 项目中引用(动态库)DLL?

c++ - 奇怪的列表打印函数行为。如果我打印 "\n"则有效,如果删除它则无效

c++ - 如何修复v8错误的 undefined reference ?

pointers - EIP寄存器如何获取其值?

c++ - 如何从指针初始化堆栈对象?

swift - 将 [NSURL] 转换为 NSUserDefaults 的 [String]?

casting - 经典 ASP 中用户提交的内容中的 'cast' 是否危险?