ConsistentProgrammer ConsistentProgrammer - 1 month ago 9
Linux Question

How to interpret data type size and its alignment?

I have a question regarding size/alignment of

double
type in linux/gcc.

On Wikipedia, it's written:


A double (eight bytes) will be 8-byte aligned on Windows and 4-byte
aligned on Linux (8-byte with -malign-double compile time option).


I understand that how an 8 byte data type is 8-byte aligned is stored in memory.

so if we have

struct foo {
double d1;
double d2;
};


I know that the size of this structure would be 16 bytes. But what will be the alignment?

Secondly, how can we visualize 8-byte size with 4-byte alignment?

As an example:

int a[2];


In the above case,
a[0]
will be Offset = 0 and
a[1]
will be at Offset =32.

But how will it be placed for
double
type in Linux (4 byte alignment)? E.g.

double d[2];


d[0]
will of course be at Offset = 0.
d[1]
should be at Offset=64, but the alignment information says that
double
is 4-byte aligned. Maybe I'm missing some point here.

Answer Source

Q1. What will be the alignment of struct foo { double d1; double d2; }?

Alignment is dependent on implementation and platform.

From gcc 5.4.0 doc, it is said that:

Note that the alignment of any given struct or union type is required by the ISO C standard to be at least a perfect multiple of the lowest common multiple of the alignments of all of the members of the struct or union in question.

So for the struct in question, we might expect its alignment to be 8, since the lowest common multiple of the alignments of its members is 8.

However, the following code shows that alignments differ between 64-bit and 32-bit platform.

// main.c

#include <stdio.h>

struct dd {
    double d1;
    double d2;
};

int main()
{
    struct dd s_dd[2];
    printf("%p\n", (void *)&s_dd[0]);
    printf("%p\n", (void *)&s_dd[1]);
}

Testing with gcc 5.4.0:

$ gcc -m64 main.c
$ ./a.out
0x7fff7ef221f0
0x7fff7ef22200
$ gcc -m32 main.c
$ ./a.out
0xff97120c  // 4-byte aligned
0xff97121c  // 4-byte aligned
$ gcc -m32 main.c -malign-double
$ ./a.out
0xfffe8178
0xfffe8188

You can check that struct dd is 4-byte aligned for 32-bit, but 8-byte aligned when compiled with -malign-double or when compiled for 64-bit.


Q2. How can we visualize 8-byte size with 4-byte alignment?

The answer to the first question already shows such a case.

By the way, you shouldn't confuse the size of the data with its alignment. As Bo Persson commented:

4 byte alignment means that the start address could be a multiple of 4 (like 0x10004), not that it stores a double in 4 bytes.