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.)