包含双字段的struct的大小

时间:2012-08-10 17:27:34

标签: c struct sizeof

首先,我理解结构中的字节填充。但我仍然有一个小测试包含struct中的双字段,我不知道如何解释这个:

typedef struct {
    char a;
    double b;
}data;

typedef struct{
    char a;
    int b;
}single;

int main(){
    printf("%d\n",sizeof(double));
    printf("%d\n",sizeof(single));
    printf("%d\n",sizeof(data));
}

通过此测试,答案为:8 816

为什么这个结果让我思考?

通过第二次测试,我们可以看到我机器上的单词大小是4个字节。

通过第一次测试,我们可以看到double的大小是8个字节。

所以,在struct data:结果应该是12个字节:char为4个字节,double为8个字节。

但是,我不知道为什么结果是16个字节。 (对我很奇怪)

请为我解释一下,谢谢:)

5 个答案:

答案 0 :(得分:8)

这是十六个字节,因此如果你有一个data的数组,double值都可以在8字节边界上对齐。在内存中正确对齐数据可以在性能上产生很大的不同。未对齐的数据操作起来可能较慢,而且获取和存储的速度较慢。

答案 1 :(得分:4)

通常用于在结构中布局数据的过程基本上是这样的:

  • 设置偏移= 0。
  • 对于结构中的每个成员:设A为其对齐要求(例如,1,2,4或8个字节,可能更多)。 Add to Offset使其成为A的倍数所需的字节数。(假设A是2的幂,可以使用Offset + = -Offset& A-1来完成。)将Offset的当前值指定为是该成员的抵消。将成员的大小添加到Offset。
  • 处理完所有成员后:让A成为任何成员的最大对齐要求。 Add to Offset使其成为A的倍数所需的字节数.Offset的最终值是结构的大小。

正如Earnest Friedman-Hill所说,最后一步是在结构的末尾添加填充,以便在它们的数组中,每个结构都以所需的对齐方式开始。

因此,对于struct { char c; double d; int32_t i; }之类的结构,在典型的实现中,您有:

  • 将偏移设置为0。
  • char需要对齐1,因此Offset已经是1的倍数(0 * 1为0)。将c放在此偏移处,0。将c,1的大小添加到Offset,使其为1。
  • double需要对齐8,所以将7添加到Offset,使其为8.将d放在此偏移处,8。将d,8的大小添加到Offset,使其为16。
  • int需要对齐4,因此Offset已经是4的倍数(4 * 4是16)。将i放在此偏移处,16。将i,4的大小添加到Offset,使其为20。
  • 最后,所需的最大对齐为8,因此将Offset加4,使其为24.此结构的大小为24字节。

注意上述内容与机器的任何字大小无关。它仅使用每个成员的对齐要求。每种类型的对齐要求可能不同,并且可能与类型的大小不同,上述内容仍然有效。

(如果对齐要求不是2的幂,则算法会中断。可以通过使最后一步将偏移量增加到所有对齐的最小公倍数的倍数来解决。)

答案 2 :(得分:3)

你有什么奇怪的(或者我错过了什么)?

逻辑是相同的(填充是根据struct中的“最大”原始字段(我的意思是 - int,double,char等)。

single一样,您有

1 (sizeof(char)) + 3 (padding) + 4 (sizeof(int))

data中的情况相同:

1 (sizeof(char)) + 
7 (padding, it's sizeof(double) - sizeof(char)) + 
8 (sizeof(double))

这是16。

答案 3 :(得分:2)

编译器可能会将所有结构大小对齐为8的倍数

答案 4 :(得分:2)

除非使用编译器特定的指令明确指定它,否则对齐取决于编译器。

变量不一定是字对齐的。有时他们会为了效率而双字对齐。在浮点的特定情况下,它们可以对齐甚至更高的值,以便SSE可以工作。

相关问题