3

使用 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;

据我了解,您可以将任何数据转换为charor unsigned char,这是允许的,但这仅适用于一种方式。

一种解决方案是制作一个union. 难道没有其他方法可以创建对unsigned char数据的不同类型的引用吗?

谢谢!大卫

4

3 回答 3

4

是的,允许以 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);

另一种选择是将有效负载创建为具有适当大小和成员的标准布局类型,然后将其视为无符号字符数组。假设您可以控制创建有效负载:

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);

这并没有违反严格的别名规则,因为它现在正朝着正确的方向发展。

于 2012-07-01T16:55:51.873 回答
1

您可以做的是创建一个数组uint32_t。通过这种方式,您可以访问它们,uint32_t也可以访问它们unsigned char:这不违反别名规则。

于 2012-07-01T15:04:39.073 回答
1

联合也将是未定义的行为。您只能char在这方面使用 - 不允许使用其他类型,包括unsigned char.

于 2012-07-01T14:48:13.977 回答