严格别名警告,产生uint32_t的参考为unsigned char阵列+偏移(Strict ali

2019-09-18 21:47发布

随着GNU GCC 4.7.0+我获得了一些严格别名警告,我想解决的问题。

我有(从硬件)有效载荷:

unsigned char payload[davidlt::PAYLOAD_SIZE];

我有这样一行:

*(uint32_t*)(payload + davidlt::DATA_OFFSET) = (pid & davidlt::PID_MASK) << davidlt::PID_SHIFT;

这在有效载荷产生一个指向特定的位置和4个字节被解释为uint32_t 。 一个新的值uint32_t类型被计算并在有效载荷代替。

我得到:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

我希望通过使用来解决它reinterpret_cast ,但我得到了同样的警告。

*reinterpret_cast<uint32_t *>(payload + davidlt::DATA_OFFSET) = (pid & davidlt::PID_MASK) << davidlt::PID_SHIFT;

我的理解,你可以转换任何数据到charunsigned char ,这是允许的,但只能一种方式。

一个解决办法是让一个union 。 不为任何其他的方法来创建不同类型的一个参考unsigned char数据?

谢谢! 大卫

Answer 1:

是的,观看数据作为char或unsigned char是允许的,但不是相反。

相反,你应该在这种情况下使用memcpy。 您的线路需要一个pid值,口罩它,移动它,然后将其插入到有效载荷。 这方面的一个直接的翻译是:

unsigned char payload[davidlt::PAYLOAD_SIZE];

uint32_t payload_pid = (pid & davidlt::PID_MASK) << davidlt::PID_SHIFT;

std::memcpy(payload + davidlt::DATA_OFFSET, &payload_pid, sizeof payload_pid);

另一个替代方案是创建有效载荷与适当的大小和部件的标准布局类型,然后,以查看它为unsigned char阵列。 假设你在创造有效载荷的控制是:

struct Payload {
    ...
    uint32_t pid;
    ...
} payload;

payload.pid = (pid & davidlt::PID_MASK) << davidlt::PID_SHIFT;

static_assert(davidlt::PAYLOAD_SIZE == sizeof(Payload), "");

unsigned char (&payload_as_char)[davidlt::PAYLOAD_SIZE] = reinterpret_cast<unsigned char (&)[davidlt::PAYLOAD_SIZE]>(&payload);

因为它现在会正确的方向,这是不违反严格别名规则。



Answer 2:

工会也将是不确定的行为。 您只能使用char在此respect-没有其他类型是允许的,这包括unsigned char



Answer 3:

你可以做的是创建数组uint32_t来代替。 这样,您就可以访问他们的uint32_t ,但也可以作为unsigned char :这并不违反混淆规则。



文章来源: Strict aliasing warning, creating uint32_t reference to unsigned char array + offset