摆脱严格的别名警告最简单的方法是什么?
代码是:
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)。
有没有什么快速、简单的方法来消除警告:
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
*((uint16_t *) &msg[1]) = bytesToRead;
^发布于 2016-07-01 21:11:41
如下所示,因为它迫使您决定16位值应该表示为:
// Little-endian.
msg[1] = bytesToRead & 0xff;
msg[2] = (bytesToRead >> 8) & 0xff;对于big-endian,颠倒右侧的顺序。
发布于 2016-07-01 21:16:32
这听起来像是在解码某种协议,所以一种方法是声明一个对应于协议数据的结构:
typedef struct
{
uint8_t something;
uint16_t bytes_to_read;
} prot_data_t;然后,为了方便起见,为了避免别名问题,您可以将以下代码放在一个联合中:
typedef union
{
prot_data_t named_data;
uint8_t raw_data [sizeof(prot_data_t)];
} protocol_t;现在,您可以通过raw_data逐字节发送/接收数据,但可以通过named_data访问不同的值。
需要考虑的一些事情:
请记住,此代码以及任何不使用位移位的解决方案都将依赖于字符顺序。
像这样的代码可能容易受到对齐和结构/联合填充问题的攻击。为了获得最大的可移植性,实际上并不推荐使用结构/联合,除非您将它们与一些序列化/反序列化例程相结合。
发布于 2016-07-01 21:22:16
这一警告是有原因的。如果msg在16位边界上启动,则msg[1]不会。因此,如果您尝试从该字段的地址开始写入16位值,则可能会触发对内存的无效写入的陷阱,并导致崩溃。
相反,您应该一次写入一个字节。假设您希望字节采用big-endian格式(也称为网络字节顺序),则可以执行以下操作:
msg[1] = (uint8_t)(bytesToRead >> 8);
msg[2] = (uint8_t)(bytesToRead);https://stackoverflow.com/questions/38145981
复制相似问题