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

Reply via email to