关于struct结构体填充造成的字节数的问题

有如下的结构体的定义:

<span style="font-size:14px;">struct aa{char a;int b;float c;double d;char* pa;int* pb;short e;};</span>问题, 求对struct进行sizeof的时候, 得到的大小数。

问题解析: 当内存中的值合理对其的时候, 很多机器能够高效的访问。 例如, 按字节寻址的32位机器中, 有两个字节的short型变量必须放在偶数地址上, 而4字节的int型变量, 必须放在4的整数倍地址上。 某些机器甚至根本不能访问没有对齐的地址。 所以必须要求所有的数据正确的对齐。

为了解决上述问题, 我们要知道, 32位机器, 对于指针变量, 无论是char型还是int型, 指针变量存的都是地址, 都占用4bytes。

下面我们一步一步分析:

<span style="font-size:14px;">struct aa{char a;};</span>上述在内存中占用1个byte。

|

<span style="font-size:14px;">struct aa{char a;int b;};</span>上述本来占据5个byte。 但是由于要求int型变量b的地址必须是4的倍数, 所以占用1(for char) + 3 (填充用的) + 4(for int), 故而占用8个bytes。| – – -| | | |

<span style="font-size:14px;"><pre name="code" class="cpp">struct aa{char a;int b;float c;};</span>上述占用了12个字节。 因为已经满足4的倍数啦。

| – – – | | | | | | | |

<span style="font-size:14px;">struct aa{char a;int b;float c;double d;};</span>

上述占用12 + 8个字节。 但是double要求地址offset从8的整数倍开始, 所以填充4个字节, 变成16, 变成8的倍数, 在存下double。 是 12 + 4 + 8 = 24 bytes:

(char)| – – – (int) | | | | (float)| | | | – – – – (double)| | | | | | | |

下面:

<span style="font-size:14px;">struct aa{char a;int b;float c;double d;char* pa;};</span>上述占用24 + 8 = 32bytes。虽然要char*pa 变量占用4bytes, 但是 因为要按照double的对其格式。

(char)| – – – (int) | | | | (float)| | | | – – – – (double)| | | | | | | | (char*) | | | | – – – –

<span style="font-size:14px;">struct aa{char a;int b;float c;double d;char* pa;int* pb;};</span>上述占用仍然是32 bytes, 因为最后已经有四个空着的bytes, 仍然满足地址是8的倍数。

(char)| – – – (int) | | | | (float)| | | | – – – – (double)| | | | | | | | (char*) | | | | (int*) | | | |

<span style="font-size:14px;"><pre name="code" class="cpp">struct aa{char a;int b;float c;double d;char* pa;int* pb;short e;};</span>上述占用时32 + 8 = 40 bytes, 因为 short要按照double的格式对其, 即总的地址要是8的倍数。

(char)| – – – (int) | | | | (float)| | | | – – – – (double)| | | | | | | | (char*) | | | | (int*) | | | | (short) | | – – – – – –

也就是最后尾部还剩下6个bytes空着了。 试想

<span style="font-size:14px;"><pre name="code" class="cpp"><pre name="code" class="cpp">struct aa{char a;int b;float c;double d;char* pa;int* pb;short e;int f;};</span>由于空6个bytes, 必须是4的倍数, 所把最后四个给占用了。 所以当然还是40bytes。 当然是。

(char)| – – – (int) | | | | (float)| | | | – – – – (double)| | | | | | | | (char*) | | | | (int*) | | | | (short) | | – – (int) | | | |

接下来,, 如果再加一个short, 就变成了48了, 当然是啦:

<span style="font-size:14px;">struct aa{char a;int b;float c;double d;char* pa;int* pb;short e;int f;short g;};</span>

编译器可能提供用于控制结构体的这种填充。 例如#pragma, 这样我们就可以屏蔽掉变量的对齐方式, 自己设定变量的对齐方式。

例如编译器提供#pragma pack(n) 来设定变量以n字节对齐的方式。 n 字节的对齐方式指的是, 如果n 大于该变量所占的字节数, 那么偏移量必须满足默认的对齐方式, 如果n 小于变量类型所占的字节数, 那么偏移量必须为n的倍数。

举例子如下:

<span style="font-size:14px;">#include <iostream>using namespace std;#pragma pack(push) // 保持对齐方式#pragma pack(4) // 设定4字节对齐struct aa{char a;int b;float c;double d;char* pa;int* pb;short e;};#pragma pack(pop) // 恢复对齐方式int main() {cout << sizeof(aa) << endl;return 0;}</span>运行结果如下:

分析如下:

4 + 4 + 4 + 8 + 4 + 4 + 4 = 32.

与其临渊羡鱼,不如退而结网。

关于struct结构体填充造成的字节数的问题

相关文章:

你感兴趣的文章:

标签云: