https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96293
--- Comment #8 from lavr at ncbi dot nlm.nih.gov --- Consider the following code: struct record { unsigned char len; unsigned short data[5]; } __attribute__((packed)); struct attribute { unsigned char code; struct record record; } __attribute__((packed)); If I had "struct attribute* a" in my code then "&a->record.data[0]" would be a well-aligned access, even though "struct record" is not "properly aligned". If I had "struct record" defined with the align(2) attribute (to cater to "short"s), it might have been placed in "struct attribute" at offset 2, leaving a one byte gap after the "code" member. Newer gcc gives even more warnings where there should be none (but fortunately, it does not leave a gap: I can't check the behavior with GCC 9 anymore because I do no longer have it). $ cat align.c #include <stdio.h> #ifdef ALIGN2 # define ALIGN __attribute__((packed, aligned(2))) #else # define ALIGN __attribute__((packed)) #endif void fun(unsigned short* n) { *n = 0xCAFE; } struct record { unsigned char len; unsigned short data[5]; } ALIGN; struct attribute { unsigned char code; struct record record; } __attribute__((packed)); int main() { struct attribute a; printf("offsetof data = %zu\n", offsetof(struct attribute, record.data[0])); fun(&a.record.data[0]); return 0; } $ gcc -Wall -o align align.c align.c: In function ‘main’: align.c:34:9: warning: taking address of packed member of ‘struct record’ may result in an unaligned pointer value [-Waddress-of-packed-member] 34 | fun(&a.record.data[0]); | ^~~~~~~~~~~~~~~~~ $ ./align offsetof data = 2 $ gcc -Wall -DALIGN2 -o align align.c align.c:26:1: warning: alignment 1 of ‘struct attribute’ is less than 2 [-Wpacked-not-aligned] 26 | } __attribute__((packed)); | ^ align.c:25:19: warning: ‘record’ offset 1 in ‘struct attribute’ isn’t aligned to 2 [-Wpacked-not-aligned] 25 | struct record record; | ^~~~~~ align.c: In function ‘main’: align.c:34:9: warning: taking address of packed member of ‘struct record’ may result in an unaligned pointer value [-Waddress-of-packed-member] 34 | fun(&a.record.data[0]); | ^~~~~~~~~~~~~~~~~ $ ./align offsetof data = 2