如何解释数据类型大小及其对齐方式?

How to interpret data type size and its alignment?

我有一个关于 size/alignment 的 double 类型的问题 linux/gcc。

Wikipedia 上写着:

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).

我了解 8 字节数据类型是如何 8 字节对齐存储在内存中的。

所以如果我们有

struct foo {
    double d1;
    double d2;
};

我知道这个结构的大小是 16 个字节。但是对齐方式是什么?

其次,我们如何可视化 4 字节对齐的 8 字节大小?

举个例子:

int a[2];

在上述情况下,a[0] 的偏移量 = 0,a[1] 的偏移量 =32。

但是double类型在Linux中如何放置(4字节对齐)?例如

double d[2];

d[0] 当然会在 Offset = 0。d[1] 应该在 Offset=64,但是对齐信息说 double 是 4 字节对齐的。也许我在这里遗漏了一些要点。

简答

对齐取决于实现和平台。对于gcc,可以通过__alignof__ C扩展关键字(gcc 5.4.0 doc)查询对象的对齐方式,就像使用sizeof运算符查询对象的大小一样。


长答案

Q1。 struct foo { double d1; double d2; }的对齐方式是什么?

以下示例代码显示,所讨论的 struct 的对齐方式在 64 位和 32 位平台上有所不同。 (使用 gcc 5.4.0 测试)

$ cat main.c
#include <stdio.h>

struct foo {
    double d1;
    double d2;
};

int main()
{
    struct foo s_foo[2];
    printf("%d\n", (int)__alignof__(struct foo));
    printf("%p\n", &s_foo[0]);
    printf("%p\n", &s_foo[1]);
}
$ gcc -m64 -o main main.c
$ ./main
8
0x7fff54213ba0
0x7fff54213bb0
$ gcc -m32 -o main main.c
$ ./main
4
0xffb5239c   # 4-byte aligned
0xffb523ac   # 4-byte aligned
$ gcc -m32 -malign-double -o main main.c
$ ./main
8
0xffb398b8
0xffb398c8

您可以检查 struct dd 对于 32 位是 4 字节对齐的,但是当使用 -malign-double 编译或为 64 位编译时是 8 字节对齐的。

Q2。我们如何可视化 4 字节对齐的 8 字节大小?

以下示例显示了此类行为。 struct foodouble 类型成员 d1 大小为 8 个字节,但它是 4 字节对齐的。

$ cat main.c
#include <stdio.h>

struct foo {
    double d1;
    double d2;
};

int main()
{
    struct foo s_foo[2];
    printf("%d\n", (int)sizeof(s_foo[0].d1));
    printf("%d\n", (int)__alignof__(s_foo[0].d1));
    printf("%p\n", &s_foo[0].d1);
}
$ gcc -m32 -o main main.c
$ ./main
8
4
0xffeca1dc