【C++】字节对齐,也就是一个结构体的实际大小

字节对齐是面试笔试经常考到的一个知识点

计算一个结构体大小只需要进行如下几个步骤即可。

1.确认结构体中所有成员的长度大小

  可以引用此表。

 

 

char

short

int

long

float

double

long long

long double

Win-32

长度

1

2

4

4

4

8

8

8

模数

1

2

4

4

4

8

8

8

Linux-32

长度

1

2

4

4

4

8

8

12

模数

1

2

4

4

4

4

4

4

Linux-64

长度

1

2

4

8

4

8

8

16

2.确定系统默认的对齐模数:

  【#pragma pack指定的数值】、【未指定#pragma pack时,vc6 中默认是8

   在下面这种形式下就是自己指定对齐模数。

  #pragma pack(2)

  struct my_struct

  {

      char a;

      long double b;

  };

  #pragma pack()

 

3.此时就会得到一组数和一个数(每个成员的大小 和 系统的模数) 按照以下方法计算即可得到总长度length=0

  1.拿出第一个成员的长度加到总长度里面  length += sizeof(member1) 因为对于第一个成员不存在对齐问题 都是从0开始

  2.拿出第二个成员的长度,和系统模数比较 拿出较小的数 min

  3.在前一个成员后面进行移动,让加上字节后的地址可以被 min整除,第二个成员的其实位置就是这个地址。 

  4.以此类推

4.最后 拿出所有成员中最大的长度max 和系统模数比较,拿出较小的totalmin,看现在的总长度能不能被totalmin整除,如果可以现在就行了,如果不可以在后面加上n让总长度可以被totalmin整除  最后就是最终大小。

 

举个例子:

  

struct my_struct

{

    char a;

    double b;

};

  第一步:获得所有成员的长度:a 的长度是 1   b的长度是 8  

  第二步:获取系统的模数  此时没有指定pack 所以用vc6中默认的即可   8

  第三步:把a算进去 现在总长度是1了,内存布局为[0] 0位置存放的就是a  然后拿出b的长度8 和默认的8比较,取出较小的 也就是8, 此时b所在的位置应该能被8整除

      但是我们看 a是从0开始的 a的长度是1  所以 必须把地址向后移动7位,让b的起始地址是8 才能保证被8整除。所以在a和b之间要加入7个空位,然后让b从8开始

      [0][1 2 3 4 5 6 7] [8 9 10 11 12 13 14 15]

  第四部:总长度为 a + b + 空  =  1 + 8 + 7 = 16 

      拿出所有成员中最长的b 也就是8  拿出系统默认的8 取较小的8

      看16能否被8整除  这里可以,所以最后长度为16

 

再来个复杂的:

  

struct my_struct

{

    int a;

    char b;

    double c;

    int d;

    char e;

}; 

  还是按照那几步骤:

    1.获取所有成员的长度 分别是 4 1 8 4 1

    2.获取系统模数 这里没自定义pack 所以是 8

    3. 第一个成员a 从0位置开始 占据[0123] 四个字节  

      然后轮到b了。因为a占据0123了 所以b从4开始   b的长度是1 ,和系统模数8比,取出小的 1 。4可以被1整除,不用补空位   此时 [0123][4 ]    0123放着a   4放着b

        然后轮到c了,c是8 和系统模数比 取出小的 8  ,01234都有 东西了,c要从5开始,但是5不能被8整除 想要被8整除,最起码要在8这个位置开始 所以567存放空位,c从8开始 此时[0 1 2 3] [4] [5 6 7] [8 9 10 11 12 13 14 15]

      现在轮到d了, d是4  系统模式是8  拿出小的 4  起始地址16 能被4整除,所以d就从16开始[0 1 2 3] [4] [5 6 7] [8 9 10 11 12 13 14 15][16 17 18 19]

      最后轮到了e,  1和8比 拿出1  起始地址为20 能被1整除,所以最后结构是[0 1 2 3] [4] [5 6 7] [8 9 10 11 12 13 14 15][16 17 18 19][20]

    4.最后拿出所有成员中最长的 是c 长度为8  和系统模数8 比 取出小的   8

       现在的总长度21不能被8整除,所以仍然要向后补3位[0 1 2 3] [4] [5 6 7] [8 9 10 11 12 13 14 15][16 17 18 19][20][21 22 23] 

      一共24字节。

 

注意:

  有指针成员,大小按照指针的大小即可。

注意:关于64位系统和32位系统的大小

  可以确定的是32位系统的指针大小为32位 也就是4字节

  64位系统的指针大小为64位 就是8字节

  但是对于int型 long double 等类型,32位64位根据系统不同大小不同。没有确定标准

  但是如果出现int32_t 或者 int64_t ,这些是为了保证可移植性而定义的类型,表示32位的int和64位的int,长度分别为固定的32位和64位

原文地址:https://www.cnblogs.com/heanqing/p/4908360.html