2
によって「間接参照型punnedポインタが厳格なエイリアシング規則を破るだろう」解決GCC警告:機能では、一時的なポインタ
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