我读到结构成员根据结构中最大的数据成员对齐。但似乎没有用。
#include <stdio.h>
struct abc
{
char a[10];
int b;
float f;
double d;
char c;
};
main()
{
printf("size : %d", sizeof(struct abc));
printf("size of double : %d", sizeof(double));
}
结构大小打印为32个字节。但我希望它打印40作为(10)+ 2填充字节+ b(4)+ f(4)+ 4填充字节+ d(8)+ c(1)+ 7填充字节。任何人都可以告诉我为什么这不能按预期工作?
答案 0 :(得分:3)
C结构根据最严格对齐的数据成员对齐,该成员可能是也可能不是最大的成员。 (在您的示例中,最大的成员是char a[10]
,其大小为10,但其对齐方式仅为1.)
精确对齐约束依赖于实现;标准提供的唯一要求是所有对齐都是2的幂。
对象的对齐不需要与其大小相同。例如,在运行Posix(类似)系统的32位Intel平台上,没有基本类型具有超过四个字节的对齐,包括八字节双精度和10字节长双精度(如果由C编译器实现)。但是其他平台ABI需要8个字节对齐的双精度数,这使得long doubles
的大小为16个字节而不是12个字节(尽管在所有情况下,硬件仅使用80位。)
大量平台和CPU相关的细节包含在名为&#34; Application Binary Interface&#34; (ABI)规格。这些规范通常不是标准,因为它们没有被国际标准机构神圣化,但它们通常受到尊重,以便允许不同编译器,链接器和系统库之间的互操作性。您可以在Linux Foundation's Referenced Specifications page上找到与Linux实施相关的一些规范列表。特别是,指定i386硬件上基本类型对齐的文档是"System V Application Binary Interface Intel386 Architecture Processor Supplement, Fourth Edition"(一个377页的PDF文件,需要与System V Application Binary Interface基础文档一起阅读,另外271页。)您将在第28页找到该图表。
答案 1 :(得分:2)
项目按照实现的要求与对齐。这是标准的允许,而不是强制要求。例如,参见{ {1}}说明了对齐的工作原理,但并未要求对特定对象存在哪些对齐方式。实质上,它必须说(我的大胆):
例如,8字节双精度可能不需要8字节对齐。最好的办法是创建一个变量,并用以下内容获取每个字段的地址:对齐是一个实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。
C11 6.2.8 Alignment of objects
我的Debian安装上的完整程序会向您显示偏移量和大小:
printf("%p\n", &(var.d));
运行它给了我:
#include <stdio.h>
struct {
char a[10];
int b;
float c;
double d;
char e;
} xyzzy;
#define describe(fld) \
printf (" " #fld ": %2zd @ %2zd (%2zd)\n", \
sizeof (xyzzy.fld), \
(((char *)(&(xyzzy.fld))) - ((char *)(&(xyzzy)))), \
_Alignof (xyzzy.fld))
int main (void) {
describe (a);
describe (b);
describe (c);
describe (d);
describe (e);
puts("=====");
printf("total: %2zd @ 0 (%2zd)\n", sizeof (xyzzy), _Alignof (xyzzy));
return 0;
}
与你看到的内容基本相同,总大小为32。
事实上,您可以看到 a: 10 @ 0 ( 1)
b: 4 @ 12 ( 4)
c: 4 @ 16 ( 4)
d: 8 @ 20 ( 4)
e: 1 @ 28 ( 1)
=====
total: 32 @ 0 ( 4)
的对齐要求不是其大小的倍数 - 将其置于double d
而不是{{ 1}}。括号内的数字是对齐要求,24
为20
。