为什么结构成员没有根据结构中最大的数据成员对齐?

时间:2014-09-20 05:37:02

标签: c

我读到结构成员根据结构中最大的数据成员对齐。但似乎没有用。

#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填充字节。任何人都可以告诉我为什么这不能按预期工作?

2 个答案:

答案 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}}。括号内的数字是对齐要求,2420