Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

alignment

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

like image 531
Chethan Avatar asked Feb 15 '13 11:02

Chethan


People also ask

Are structs 8 byte aligned?

struct foo1 { char *p; char c; long x; }; Assuming a 64-bit machine, any instance of struct foo1 will have 8-byte alignment.

How many bytes of alignment does the struct as a whole require?

As we mentioned on the top, the alignment requirement of double is 8 bytes. Inorder to avoid such misalignment, compiler will introduce alignment requirement to every structure. It will be as that of the largest member of the structure.

What is structure member alignment?

Data structure alignment is the way data is arranged and accessed in computer memory. Data alignment and Data structure padding are two different issues but are related to each other and together known as Data Structure alignment.

What does it mean to be byte aligned?

A memory address a is said to be n-byte aligned when a is a multiple of n (where n is a power of 2). In this context, a byte is the smallest unit of memory access, i.e. each memory address specifies a different byte.


Video Answer


2 Answers

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.

like image 158
Potatoswatter Avatar answered Nov 14 '22 21:11

Potatoswatter


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.

like image 23
Steve Jessop Avatar answered Nov 14 '22 22:11

Steve Jessop