5
#include<stdio.h>

int main()
{
    struct test
    {
        char c;
        int y;
        float r;
        double d;
    } t1; 
    printf("%d\n",sizeof(t1));
    return 0;
}   

输出:我的 gcc 4.3.2 Ubuntu 12.04 上的 24

输出:运行代码的 Ideone 链接上的 20

我的解释: 我认为 24​​ 是对的。如果我错了,请纠正我?

  1. 第一个块将被 Char 'c' 占用。1 个字节为自己,后跟 3 个字节的填充。
  2. 第二块将由整数'y'占用。(在这种情况下不需要填充,因为整数是 4 字节。所以它将完全填充块)。
  3. 第 3 个块将被 float 'r' 占用。(不需要填充,因为 float 也是 4 个字节)。
  4. 现在将填充下一个 4 字节的块,因为 next 是双倍的。并且存储地址必须是该数据类型大小的倍数。
  5. 接下来的 2 个 4 个字节的块将被双变量占用。

因此Size = 1(char) + 3(Padded in Char case) + 4(int) + 4(float) + 4(padded for Double) + 8(double) = 24

为了清晰:

由于块被采用 4 字节集合。所以每个地址都是 4 的倍数。对于 double ,下一个地址必须是 1012。但它不是 8 的倍数。所以填充它!并从 1016 内存布局 我的问题开始 - 24 是否正确,我的解释是否正确,或者我的解释是错误的,请解释一下?

4

2 回答 2

5

您的解释是正确的,因为特定的编译器会为该结构输出具有特定布局的二进制文件。如果您正确预测了输出,那么您的预测显然对于您在此特定时间的特定设置是正确的。

但是结构的大小无论如何都不是在 C 中严格定义的。在本主题中定义的唯一内容是结构成员的顺序和第一个成员的偏移量。填充,因此结构的总大小是未定义的,它由编译器决定。显然,编译器填充结构的主要原因是通过根据成员的各个类型正确对齐成员来提高性能(正如您正确指出的那样)。但是(这在这里很重要)编译器会根据目标架构选择最有效的填充。例如,如果一个架构有一个 128 位的 int,你可以想象你的结构体的大小会有多么不同。

因此,如果涉及到 C 语言的定义方面(或您所描述的以外的任何设置),您的预测将是毫无根据的。它自然会匹配某些设置,但只是偶然。

于 2013-06-20T16:26:45.843 回答
1

填充用于使用指令优化。C 语言没有指定任何关于填充的内容。唯一的问题是,如果 loadq(8 字节日期)不是从 8 字节地址边界开始,就会发生 H/W 陷阱。所以,我当然可以为这个示例数据结构编写一个没有任何填充的编译器。唯一的问题是我需要使用 loadb / storb 指令而不是 loadl / storl / loadq / storq 指令,这看起来很愚蠢。如果 Ideone 使用 loadl / storl 而不是 loadq / storq,则 20 字节大小是可以的,并且 float 和 double 之间的填充是不必要的。

顺便说一句,我有一种在结构中按顺序声明 8byte、4byte、2byte、1byte 数据的做法,并且可能在所有可能的地方......

于 2013-06-21T02:32:27.707 回答