如何解释数据类型大小及其对齐方式?
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 foo
的 double
类型成员 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
我有一个关于 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 foo
的 double
类型成员 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