问题:

问题1:

  1. struct X
  2. {
  3. char a; //1
  4. float b; //4
  5. int c; //4
  6. double d; //8
  7. unsigned e; //4
  8. };

由于存储变量时地址对齐的要求,所以这个结构体大小应该是32。

解答:

  1. struct X {
  2. char a; // 1 bytes
  3. char padding1[3]; // 3 bytes
  4. float b; // 4 bytes--
  5. int c; // 4 bytes
  6. char padding2[4]; // 4 bytes--
  7. double d; // 8 bytes--
  8. unsigned e; // 4 bytes
  9. char padding3[4]; // 4 bytes--
  10. };

注意:

  1. 对于所有基本类型,align(T)==sizeof(T)
    • align(X) 是多少呢?当然就是所有成员里面 align 最大的那个,是 align(d)==8

padding1的存在是因为,offset(b)必须能够被align(b)整除,所以塞三个char

b的偏移字节是它自身字节的整数倍,因此要添加三个字节的偏移

padding2的存在是因为,offset(d)必须能够被align(d)整除,所以塞4个char

原因同上

padding3的存在是因为,因此sizeof(X)必须能够被align(X)整除,就有了。

整个结构体的大小必须能被其中最大align的数整除。

备注:
C++内置的offsetof函数,能自动返回结构对象中,某变量距离结构体对象首地址的偏移值:

  1. offsetof(s, m);

参数:

  1. 第一个参数是一个结构体
  2. 第二个参数是这个结构体中变量的名字

这个宏会返回那个变量距结构体头部的字节偏移量(Byte Offset)。

问题2: 如果我多定义一个任意型的指针

  1. struct X
  2. {
  3. char a;
  4. float b;
  5. int c;
  6. double d;
  7. unsigned e;
  8. int *f;
  9. };

结果这样结构体大小就直接变成40了。
如果指针大小是地址总线大小的话,2个指针就是8字节,加上原来的32字节也刚好等于40字节,并且也满足存储变量时地址对齐的要求。但是为什么刚才加一个指针不变,两个就变了。

解答:

  1. struct X {
  2. char a; // 1 bytes
  3. char padding1[3]; // 3 bytes
  4. float b; // 4 bytes--
  5. int c; // 4 bytes
  6. char padding2[4]; // 4 bytes--
  7. double d; // 8 bytes--
  8. unsigned e; // 4 bytes
  9. int *f; // 4 bytes--
  10. };

解答: 再加一个指针以后

  1. struct X {
  2. char a; // 1 bytes
  3. char padding1[3]; // 3 bytes
  4. float b; // 4 bytes--
  5. int c; // 4 bytes
  6. char padding2[4]; // 4 bytes--
  7. double d; // 8 bytes--
  8. unsigned e; // 4 bytes
  9. int *f; // 4 bytes--
  10. double *g; // 4 bytes
  11. char padding3[4]; // 4 bytes--
  12. };