2
在功能解决GCC警告:“提领类型punned指针将打破严格走样规则”的临时指针
size_t csps_socket_read(csps_socket_t *s, csps_packet_wrapper_t *packet, size_t sz)
我得到警告:“提领型punned指针将打破严格走样规则对下面的行[-Wstrict走样]“:
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会失去踪迹。您的代码具有未定义的行为,并可能在各种情况下崩溃,或者可能不会;它也取决于位字段的布局是非常多的实现定义。此外,需要检查'receive_mem'的对齐方式 - 如果uint16_t成员未对齐,则可能导致崩溃 –
我建议使用'memcpy',如下所示:http://stackoverflow.com/q/17789928您可以看到在任何优化级别下,编译器都能够将它理解为类型双击并省略实际的内存副本。 https://godbolt.org/g/r6VoO0 – ephemient
@AnttiHaapala请注意OP在问GCC问题,而不是如何重写代码以避免UB。 – yugr