Chethan
Chethan

Reputation: 933

Why is a double member in struct not aligned on 8 byte boundary?

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

Answers (3)

Potatoswatter
Potatoswatter

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

Steve Jessop
Steve Jessop

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

Anonymous
Anonymous

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

Related Questions