Dear GCC Experts,

I am trying to understand the subtleties of __attribute__((packed)). I have some code that works on x86, where unaligned accesses work, but fails on ARM where they do not.

As far as I can see, if I declare a struct with the packed attribute applied to the whole struct, like this:

struct test {
  int a;
  int b;
} __attribute__((packed));

and then use it like this:

{
  char c;
  struct test t;
}

Then t will be packed next to c, and t.a and t.b will be unaligned. This is not what I want!

There are lots of examples in the Linux kernel headers (if you have a source tree handy, grep for them). Here's one example picked at random:

#define FDDI_K_OUI_LEN  3
struct fddi_snap_hdr
        {
        __u8    dsap;                                   /* always 0xAA */
        __u8    ssap;                                   /* always 0xAA */
        __u8    ctrl;                                   /* always 0x03 */
        __u8    oui[FDDI_K_OUI_LEN];    /* organizational universal id */
        __be16  ethertype;                              /* packet type ID field 
*/
        } __attribute__ ((packed));

As far as I can see, making this packed can only cause trouble. If packed wasn't there there would still be no gaps between the fields - would there? - and variables of this type would be word-aligned, so the 16-bit field would be 16-bit aligned, and it would work on an ARM. But by declaring it as packed then a variable of this type will be packed at any alignment (e.g. char c; struct fddi_snap_hdr x;) and the 16-bit field may be unaligned.

Am I completely misunderstanding all of this?

I am using gcc 4.1.2.

Here is the test that I have been using to investigate this:

struct test {
  int a;
  int b;
}__attribute__((packed));
char c = 1;
struct test t = { .a=2, .b=3 };

arm-linux-gnu-gcc -S test.c

        .file   "test.c"
        .global c
        .data
        .type   c, %object
        .size   c, 1
c:
        .byte   1
        .global t
        .type   t, %object
        .size   t, 8
t:
        .4byte  2
        .4byte  3
        .ident  "GCC: (GNU) 4.1.2 20061028 (prerelease) (Debian 4.1.1-19)"


Many thanks in advance for any advice.

Regards,

Phil.

(you're welcome to Cc: any replies as I'm subscribed to the digest.)




Reply via email to