内存对齐

#pragma pack(8)

struct TestStruct4 {

char a;

long b;

};
struct TestStruct5 {

char c;

TestStruct4 d;

long long e;

};

#pragma pack() 

问题: A),sizeof(TestStruct5) = ?

B), TestStruct5 的 c 后面空了几个字节接着是 d?

TestStruct4 中,成员 a 是 1 字节默认按 1 字节对齐,指定对齐参数为 8,这两个值中取 1,a 按 1 字节对齐;成员 b 是 4 个字节,默认是按 4 字节对齐,这时就按 4 字节对齐,所以 sizeof(TestStruct4)应该为 8;

TestStruct5 中,c 和 TestStruct4 中的 a 一样,按 1 字节对齐,而 d 是个结构,它是 8 个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大 的一个,TestStruct4 的就是 4。所以,成员 d 就是按 4 字节对齐。成员 e 是 8 个字节,它是默认按 8 字节对齐,和指定的一样,所以它对到 8 字节的边界上,这时,已经使用了 12 个字节了,所以又添加了 4 个字节的空,从第 16 个字节开始放置成员 e。这时,长度为 24,已经可以被 8(成员 e 按 8 字节对齐)整除。这样,一共使用了 24 个字节。内存布局如下(*表示空闲内存,1 表示使用内存。 单位为 1byete):

                                            a       b

TestStruct4 的内存布局:1***,1111,

                                          c             d(TestStruct4.a    TestStruct4.b )      e

TestStruct5 的内存布局: 1***,         1***,               1111, ****,                11111111 

这里有三点很重要:
首先,每个成员分别按自己的方式对齐,并能最小化长度。 其次,复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度。 然后,对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐。

补充一下,对于数组,比如:char a[3];它的对齐方式和分别写3个char是一样的。也就是说它还是按1个字节对齐。如果写: typedef char Array3[3];Array3 这种类型的对齐方式还是按 1 个字节对齐,而不是按它的长度。

但是不论类型是什么,对齐的边界一定是 1,2,4,8,16,32,64....中的一个。 

posted @ 2016-02-22 17:48  湘岳  阅读(194)  评论(0编辑  收藏  举报