严格的别名警告,创建uint32_t引用unsigned char array + offset [英] Strict aliasing warning, creating uint32_t reference to unsigned char array + offset

查看:165
本文介绍了严格的别名警告,创建uint32_t引用unsigned char array + offset的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我得到:

 警告:取消引用类型指针将会破坏严格别名规则[-Wstrict-aliasing] 
pre>

我希望使用 reinterpret_cast 来解决它,但我得到相同的警告。

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

根据我的理解,你可以将任何数据转换为 char unsigned char ,这是允许的,但只有一种方式。



一个解决方案是make a union 。没有任何其他方法来创建不同类型的引用 unsigned char 数据?



谢谢!
david

解决方案

是,允许以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 id
...
}有效载荷;

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

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


With GNU GCC 4.7.0+ I got a few strict aliasing warnings, which I would like to resolve.

I have a payload (from hardware):

unsigned char payload[davidlt::PAYLOAD_SIZE];

I had this line:

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

This creates a pointer to a specific location in payload and 4 bytes are interpreted as uint32_t. A new value uint32_t type is calculated and replaced in the payload.

I get:

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

I was hoping to solve it by using reinterpret_cast, but I get the same warning.

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

As I understood you can convert whatever data to char or unsigned char, which is allowed, but that works only one way.

One solution would be to make a union. Aren't were any other way to create a reference of different type to unsigned char data?

Thanks! david

解决方案

Yes, viewing data as char or unsigned char is allowed, but not the reverse.

Instead you should use memcpy in this case. Your line takes a pid value, masks it, shifts it, and then inserts it into the payload. A direct translation of this would be:

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

Another alternative would be to create your payload as a standard layout type with the appropriate size and members, and then to view it as an unsigned char array. Assuming you're in control of creating the payload:

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

This isn't violating the strict aliasing rule because it's going the right direction now.

这篇关于严格的别名警告,创建uint32_t引用unsigned char array + offset的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆