解决GCC警告:“;取消引用类型双关指针将打破严格的别名规则;通过临时指针
在函数中解决GCC警告:“;取消引用类型双关指针将打破严格的别名规则;通过临时指针,c,pointers,gcc,strict-aliasing,type-punning,C,Pointers,Gcc,Strict Aliasing,Type Punning,在函数中 size_t csps_socket_read(csps_socket_t *s, csps_packet_wrapper_t *packet, size_t sz) 我得到警告:“取消引用类型punned指针将打破严格的别名规则[-Wstrict aliasing]”在下面的一行: packet_size = ((csps_packet_full_header_t *)s->receive_mem)->size + header_size; 如果我这样重写: csps
size_t csps_socket_read(csps_socket_t *s, csps_packet_wrapper_t *packet, size_t sz)
我得到警告:“取消引用类型punned指针将打破严格的别名规则[-Wstrict aliasing]”在下面的一行:
packet_size = ((csps_packet_full_header_t *)s->receive_mem)->size + header_size;
如果我这样重写:
csps_packet_full_header_t *packet_full_header = (csps_packet_full_header_t *)s->receive_mem;
packet_size = packet_full_header->size + header_size;
我没有得到任何警告。为什么?问题仍然存在,但gcc看不到吗
以下是涉及的结构:
typedef struct csps_socket_t_
{
void* fp;
bool open;
uint8_t receive_mem[CSPS_SOCKET_MEM];
uint32_t receive_index;
} csps_socket_t;
typedef struct ATTR_PACKED csps_packet_full_header_t_
{
uint8_t version:4;
uint8_t pclass:4;
uint8_t ch:1;
uint8_t reserved:7;
uint16_t size;
uint16_t sequence;
uint16_t checksum;
uint8_t src[8];
uint8_t dst[8];
} csps_packet_full_header_t;
基本上,这是GCC的
-Wstrict别名机制中的一个缺陷。众所周知,它既会产生错误警告,也会忽略真实的别名冲突(请参阅开发人员提供的)
在这两种情况下都存在问题,强制转换不相关的结构将违反别名规则,并可能导致GCC生成意外代码。是的,问题仍然存在,但当您使用中间变量时,GCC似乎失去了跟踪。您的代码有未定义的行为,可能在各种情况下崩溃,也可能没有;这也取决于具体的情况,而且位字段的布局在很大程度上是由实现定义的。此外,需要检查receive\u mem
的对齐情况-如果uint16\u t成员未对齐,这可能会导致Crassesi建议使用memcpy
,正如下面的回答:您可以看到,在任何优化级别下,编译器都能够将其理解为类型双关,并忽略实际的内存副本@AnttiHaapala请注意,OP询问的是GCC中的问题,而不是如何重写代码以避免UB。@yugr问题的一部分是“问题还在吗?”@AnttiHaapala是的,+1'编辑了您的评论。