【问题标题】:How to interpret data type size and its alignment?如何解释数据类型大小及其对齐方式?
【发布时间】:2017-12-05 07:08:00
【问题描述】:

我对 linux/gcc 中 double 类型的大小/对齐有疑问。

Wikipedia 上写着:

双精度(8 字节)在 Windows 上是 8 字节对齐的,在 4 字节上对齐 在 Linux 上对齐(带有 -malign-double 编译时间选项的 8 字节)。

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

如果我们有

struct foo {
    double d1;
    double d2;
};

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

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

举个例子:

int a[2];

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

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

double d[2];

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

【问题讨论】:

  • 写一个打印出大小和地址的测试程序怎么样?
  • “我知道这个结构的大小是 16 字节” - 假设错误.. 请提供标准参考。维基百科的陈述要么是错误的,要么是不完整的引用。
  • 维基百科的引用非常具体到编译选项 (-malign-double)。在实践中,如果没有这些特定的编译选项,对齐通常是大小的倍数,而不是它的一小部分。
  • 收到好的答案后,您想用它做什么?为什么知道对齐对您很重要?
  • 4 字节对齐意味着起始地址可以是 4 的倍数(如 0x10004),而不是在 4 个字节中存储 double

标签: c linux types memory-alignment


【解决方案1】:

简答

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


长答案

第一季度。 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 字节对齐。

第二季度。我们如何可视化 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

【讨论】:

  • 感谢您提供如此详细的回答!我明白了。
猜你喜欢
  • 1970-01-01
  • 2016-03-19
  • 1970-01-01
  • 2011-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-21
相关资源
最近更新 更多