Reputation: 933
This is about memory alignment. In code below, I expected that the offset of b inside the structure to be 8 (32-bit machine). See here. There by, making b
always occur within a cache line. However, that's not the case. The member b
in a global object of struct test1
seems to be aligned. I am not sure if its by chance or compiler is doing this deliberately.
I wanted to understand why compiler is not padding 4 bytes after a
.
struct test1
{
int a;
double b;
}t1;
int main()
{
struct test1 *p = malloc(sizeof(struct test1));
printf("sizes int %d, float %d, double %d, long double %d\n", sizeof(int), sizeof(float), sizeof(double), sizeof(long double));
printf("offset of b %d\n",(int)&(t1.b)-(int)&(t1));
printf("\naddress of b (on heap) = %p, addr of b (on data seg) = %p\n",&(p->b), &(t1.b));
return 0;
}
The output is...
sizes int 4, float 4, double 8, long double 12
offset of b 4
address of b (on heap) = 0x804a07c, addr of b (on data seg) = 0x80497e0
I am using standard gcc compiler on ubuntu 10.04
Upvotes: 5
Views: 3024
Reputation: 137770
According to the System V ABI for i386, page 28, double
only gets 4 bytes alignment, but compilers are recommended to provide an option for 8 bytes as well. It appears this is what is implemented by GCC on Linux, the option being called -malign-double
.
Another alternative is to use -m64
to get x86-64 object code, which is already the default on some systems including Mac OS X.
Upvotes: 5
Reputation: 279195
I expected that the offset of b inside the structure to be 8 (32-bit machine). See here
Your references explain why it could be advantageous to 8-align doubles. This doesn't amount to a guarantee that doubles will always be 8-aligned. If your sources say that they're always 8-aligned, and you observe an implementation in which they aren't, then your sources are wrong.
From the GCC man page:
Aligning "double" variables on a two word boundary will produce code that runs somewhat faster on a Pentium at the expense of more memory.
So GCC's stated reason for 4-alignment is to save memory. You can use -malign-double
and -mno-align-double
to control that, although of course you risk creating binary incompatibilities if you share structs between code compiled with conflicting options. For particular objects/struct members you can use GCC's own __attribute__((aligned))
, _Alignas
(in C11) or alignas
(in C++11), all of which can take an integer constant to specify the required alignment.
Upvotes: 4
Reputation: 21
There is no guarantee about alignment, at all, in ANSI C.
The alignment happens with automatic variables more than with anything declared on the heap. If you're on a POSIX OS, use memalign(3) to receive memory that you're sure is aligned. Malloc may return memory at any offset. You can use compiler directives like __attribute__ ((__packed__))
to put in your own alignments.
Upvotes: 0