4

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

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 个字节。(对我来说很奇怪)

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

4

5 回答 5

8

它有 16 个字节,因此如果您有一个datas 数组,则这些double值都可以在 8 字节边界上对齐。在内存中正确对齐数据可以对性能产生很大影响。未对齐的数据可能操作起来更慢,获取和存储也更慢。

于 2012-08-10T17:31:35.077 回答
5

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

  • 设置偏移量 = 0。
  • 对于结构中的每个成员: 令 A 为其对齐要求(例如,1、2、4 或 8 个字节,可能更多)。将使其成为 A 的倍数所需的字节数添加到Offset += -Offset & A-1Offset这个成员的。将成员的大小添加到 Offset。
  • 处理完所有成员后:设A为任何成员的最大对齐要求。将需要的字节数添加到偏移量,使其成为 A 的倍数。偏移量的最终值是结构的大小。

正如 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 的幂,则算法会中断。这可以通过使最后一步将偏移量增加到所有对齐的最小公倍数的倍数来解决。)

于 2012-08-10T18:01:25.183 回答
3

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

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

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。

于 2012-08-10T17:32:14.447 回答
2

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

于 2012-08-10T17:32:02.373 回答
2

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

变量不一定是字对齐的。有时它们是双字对齐以提高效率。在浮点的特定情况下,它们可以对齐到更高的值,以便 SSE 可以工作。

于 2012-08-10T17:32:47.613 回答