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
struct foo1 { char *p; char c; long x; }; Assuming a 64-bit machine, any instance of struct foo1 will have 8-byte alignment.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With