C结构的数据对齐方式

时间:2019-07-03 20:30:41

标签: c memory struct memory-alignment

在CS:APP中,以下结构中所有字段的字节偏移存在问题(3.45)。

struct {
  int    *a;
  float  b;
  char   c;
  short  d;
  long   e;
  double f;
  int    g;
  char   *h;
} rec;

这是本书的答案,它为c提供了三个字节的填充,d为两个字节的填充,而g为四个字节的填充。

field  size  offset
-----  ----  ------
a      8     0
b      4     8
c      1     12
d      2     16
e      8     24
f      8     32
g      4     40
h      8     48

这是我的解决方案,它仅给c填充1个字节,而g填充4个字节。

field  size  offset
-----  ----  ------
a      8     0
b      4     8
c      1     12
d      2     14
e      8     16
f      8     24
g      4     32
h      8     40

那么,我的解决方案有什么问题?似乎符合对齐规则(编辑*这里的“规则”只是我自己的简化概念摘要,未完成或一般),所有对象的偏移量都是对象大小的倍数。

非常感谢您的解释。

2 个答案:

答案 0 :(得分:3)

鉴于所示对象的大小和对齐规则,即说这些对象中的每一个都必须对齐其大小的倍数,然后,当结构仅以对齐所需的填充进行布局时,偏移量应如图所示在Tetrau的解决方案中。这本书的解决方案不正确。

Tetrau解决方案中显示的偏移量实际上是Apple LLVM 10.0.1使用Clang 1001.0.46.4为x86-64编译产生的偏移量;下面程序的输出是:

0
8
12
14
16
24
32
40
48
struct foo {
  int    *a;
  float  b;
  char   c;
  short  d;
  long   e;
  double f;
  int    g;
  char   *h;
} rec;


#include <stddef.h>
#include <stdio.h>


int main(void)
{
    printf("%zu\n", offsetof(struct foo, a));
    printf("%zu\n", offsetof(struct foo, b));
    printf("%zu\n", offsetof(struct foo, c));
    printf("%zu\n", offsetof(struct foo, d));
    printf("%zu\n", offsetof(struct foo, e));
    printf("%zu\n", offsetof(struct foo, f));
    printf("%zu\n", offsetof(struct foo, g));
    printf("%zu\n", offsetof(struct foo, h));
    printf("%zu\n", sizeof rec);
}

注意

一个对象需要与其大小的倍数对齐的规则对于此练习是合适的,但应注意,这不是一般规则。一台机器可能有八个字节的对象,但是只有一个总线和其他四个字节宽的内存访问特征,因此它最多只关心任何对象的四字节对齐。或者,结构成员可能是另一个结构,即大小为9个字节(例如struct bar { char x[9]; }),但其对齐要求将不是9个字节。

答案 1 :(得分:3)

答案取决于编译器,平台和编译选项。一些例子: enter image description here

https://godbolt.org/z/4tAzB_

这本书的作者不理解我担心的话题。