首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C-如何处理严格的别名警告

C-如何处理严格的别名警告
EN

Stack Overflow用户
提问于 2016-07-01 20:54:05
回答 4查看 134关注 0票数 2

摆脱严格的别名警告最简单的方法是什么?

代码是:

代码语言:javascript
复制
uint8_t msg[3];
int retval;

msg[0] = (uint8_t) INT_READ_EVENT;
*((uint16_t *) &msg[1]) = bytesToRead;

retval = write(intPipe[1], msg, sizeof(msg));

bytesToRead作为uint16_t值传递。

在另一端,有一个读取器,它接收单个字节以在处理剩余数据之前识别事件类型(在本例中为INT_READ_EVENT)。

有没有什么快速、简单的方法来消除警告:

代码语言:javascript
复制
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
    *((uint16_t *) &msg[1]) = bytesToRead;
    ^
EN

回答 4

Stack Overflow用户

发布于 2016-07-01 21:11:41

如下所示,因为它迫使您决定16位值应该表示为:

代码语言:javascript
复制
// Little-endian.
msg[1] = bytesToRead & 0xff;
msg[2] = (bytesToRead >> 8) & 0xff;

对于big-endian,颠倒右侧的顺序。

票数 3
EN

Stack Overflow用户

发布于 2016-07-01 21:16:32

这听起来像是在解码某种协议,所以一种方法是声明一个对应于协议数据的结构:

代码语言:javascript
复制
typedef struct
{
  uint8_t  something;
  uint16_t bytes_to_read;
} prot_data_t;

然后,为了方便起见,为了避免别名问题,您可以将以下代码放在一个联合中:

代码语言:javascript
复制
typedef union
{
  prot_data_t named_data;
  uint8_t     raw_data [sizeof(prot_data_t)];
} protocol_t;

现在,您可以通过raw_data逐字节发送/接收数据,但可以通过named_data访问不同的值。

需要考虑的一些事情:

请记住,此代码以及任何不使用位移位的解决方案都将依赖于字符顺序。

像这样的代码可能容易受到对齐和结构/联合填充问题的攻击。为了获得最大的可移植性,实际上并不推荐使用结构/联合,除非您将它们与一些序列化/反序列化例程相结合。

票数 3
EN

Stack Overflow用户

发布于 2016-07-01 21:22:16

这一警告是有原因的。如果msg在16位边界上启动,则msg[1]不会。因此,如果您尝试从该字段的地址开始写入16位值,则可能会触发对内存的无效写入的陷阱,并导致崩溃。

相反,您应该一次写入一个字节。假设您希望字节采用big-endian格式(也称为网络字节顺序),则可以执行以下操作:

代码语言:javascript
复制
msg[1] = (uint8_t)(bytesToRead >> 8);
msg[2] = (uint8_t)(bytesToRead);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38145981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档