Packing of structure fields and whole structs

Phil Endecott spam_from_gcc_2@chezphil.org
Wed Dec 6 16:48:00 GMT 2006


Let me make this concrete again.  With this test program:

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

char c = 1;
struct test t = { .a=2, .b=3 };

what can I assume about the alignment of t.a?  As I now understand it, 
t.a and t.b both have alignment of 1, so t has alignment of 1, so t can 
be packed immediately after c with no gap.  It is then unsafe (on some 
hardware) to take &t.a and pass it to a function that wants an int*.

What does gcc actually do?  Well on x86, it does indeed pack t 
immediately after c:

	.file	"test2.c"
globl c
	.data
	.type	c, @object
	.size	c, 1
c:
	.byte	1
globl t
	.type	t, @object
	.size	t, 8
t:
	.long	2
	.long	3
	.ident	"GCC: (GNU) 4.1.2 20060920 (prerelease) (Debian 4.1.1-14)"
	.section	.note.GNU-stack,"",@progbits

On the other hand, on ARM it leaves a gap:

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


But, if I declare struct test like this:

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

then the ARM compiler generates the same layout as the x86 compiler, 
without the gap.

The practical consequence of this is that making the "harmless" change 
of moving the attribute from the members to the struct as a whole 
causes code that previously worked to not work.  Would you say that 
such code was "always wrong", or is there an issue here?

Thanks for all the advice.


Phil.






More information about the Gcc-help mailing list