可能存在严格的别名违规吗?

k h*_*ang 2 c++ strict-aliasing undefined-behavior c++20

我滚动浏览了一些帖子,并读到了有关严格别名规则的内容。它看起来非常接近我在俱乐部项目中看到的一些代码,相关片段如下。

LibSerial::DataBuffer dataBuffer;
size_t BUFFER_SIZE = sizeof(WrappedPacket);

while(true) {
    serial_port.Read(dataBuffer, sizeof(WrappedPacket));
    uint8_t *rawDataBuffer = dataBuffer.data();

    //this part
    auto *wrappedPacket = (WrappedPacket *) rawDataBuffer;
...
Run Code Online (Sandbox Code Playgroud)

结构体定义是:

typedef struct __attribute__((__packed__)) TeensyData {
    int16_t adc0, adc1, adc2, adc3, adc4, adc5, adc6, adc7, adc8, adc9, adc10, adc11;
    int32_t loadCell0;
    double tc0, tc1, tc2, tc3, tc4, tc5, tc6, tc7;
} TeensyData;

typedef struct __attribute__((__packed__)) WrappedPacket {
    TeensyData dataPacket;
    uint16_t packetCRC;
} WrappedPacket;
Run Code Online (Sandbox Code Playgroud)

希望很明显我是 C++ 新手。那么1)这是否违反了规则?2)如果是,有哪些替代解决方案?

Ben*_*igt 6

是的,这是违规的。该规则允许您使用原始字节访问 ( char*unsigned char*std::byte*) 来访问其他数据类型。它不允许您使用其他数据类型来访问原始字节数组。

解决方案是memcpy

WrappedPacket wpkt;
std::memcpy(&wpkt, dataBuffer.data(), sizeof wpkt);
Run Code Online (Sandbox Code Playgroud)

  • 作为经常做这样的事情的人:我强烈建议您显式反序列化来自外部设备的数据,因为它显然在这里。强制转换和普通 memcpy 都无法保护您免受字节序、意外填充等问题的影响。 (2认同)