#include<stdio.h>
int main()
{
struct test
{
char c;
int y;
float r;
double d;
} t1;
printf("%d\n",sizeof(t1));
return 0;
}
输出: 24我的gcc 4.3.2 Ubuntu 12.04
输出:Ideone Link for Running Code
上的20我的解释: 我认为24是对的。如果我错了,请纠正我?
因此Size = 1(char) + 3(Padded in Char case) + 4(int) + 4(float) + 4(padded for Double) + 8(double) = 24
清晰度:
由于Chunks采用4字节采集。所以每个地址都是4的倍数。 对于double,Next地址必须是1012.但它不是8的倍数。所以填充它!并从1016年开始 我的问题 - 24是正确的,我的解释是正确的还是我的解释是错的,请解释一下?
答案 0 :(得分:5)
在特定编译器输出具有该结构的特定布局的二进制文件的意义上,您的解释是正确的。如果您已正确预测输出,那么您的预测显然正确,以便在此特定时间进行特定设置。
但结构的大小不是,无论如何,在C中严格定义。在这个主题中唯一定义的是结构成员的顺序和第一个成员的偏移量。填充,因此结构的总大小未定义,并且它作为编译器的决定而留下。显然,编译器填充结构的主要原因是通过基于各个类型的成员的正确对齐来提高性能(正如您正确指出的那样)。但是(这在这里很重要)编译器根据目标架构选择最有效的填充。例如,如果体系结构具有128位int,则可以想象结构的大小将如何根本不同。
所以,如果涉及到C语言的定义方面(或者除了你所描述的以外的任何设置)你的预测将毫无根据。它自然会匹配一些设置,但只是偶然。
答案 1 :(得分:1)
Padding用于使用指令优化。 C语言没有指定任何有关填充的内容。唯一的问题是,如果loadq(8字节日期)没有从8字节地址边界开始,则会发生H / W陷阱。因此,对于此示例数据结构,我当然可以编写一个没有任何填充的编译器。唯一的问题是我需要使用loadb / storb指令而不是看起来很愚蠢的loadl / storl / loadq / storq指令。如果Ideone使用loadl / storl而不是loadq / storq,则20字节大小正常,并且不需要float和double之间的填充。
顺便说一下,我有一种在结构中按顺序声明8byte,4byte,2byte,1byte数据的做法,并且可能是每个可能的......