C语言结构体内存对齐
结构体是C语言常用的数据结构,它也是C语言支持的唯一一种聚合类型。在编译器为某个结构体分配的时候,原来相邻的的成员的内存却未必是相邻的。这是怎么回事呢?请往下看。
观察一下下面的结构体:
struct {
char am1;
short am2;
int am3;
short am4;
int am5;
}s1;
很明显,该结构体有5个成员变量,那么结构体s1占用空间会是各个成员占用的空间之和吗?它们的内内存地址会是连续的吗?
我们用一段程序看一下实际的情况:
int main()
{
cout<<sizeof(int)<<" "<<sizeof(short)<<" "<<sizeof(char)<<endl;
cout<<"sizeof(s1)£º"<<sizeof(s1)<<endl;
cout << "&(s1.am1)"<<(uint32_t)&(s1.am1)<<" &s1.am2"<<(uint32_t)&s1.am2<<" &s1.am3 "<<(uint32_t)&s1.am3<<" &s1.am4"<<(uint32_t)&s1.am4<<" &s1.am5"<<(uint32_t)&s1.am5 << endl;
return 0;
}
上面的代码很简单,就是看一下编译器认为结构体s1应该占用的空间是多大。好了不多说了,来看一下运行结果。
下面是运行结果:
4 2 1
sizeof(s1):16
&(s1.am1):5005324 &s1.am2:5005326 &s1.am3:5005328 &s1.am4:5005332 &s1.am5:5005336
Process returned 0 (0x0) execution time : 0.829 s
Press any key to continue.
结构体s1占用的空间是16字节,明显不是各个成员的占用大小之和。
这是怎么回事呢?
其实是编译器在为该结构分配内存的时候,会尽量为每个成员分配在为4的整数倍的地址处 。可以想象为编译器每次取出4的连续字节的内存来摆放结构体成员,在上面的例子中,第一次取出的4字节可以储存am1, am2,然后空一个字节。再取4字节摆放后面的am3;再取4字节摆放short类型的am4,虽然后面还空两个字节,但是由于寻址的原因这两个字节已经不能用了,最后就是再取4字节储存int 类型的am5了。
从上面的运行结果也可以看出,am2的地址与am3的地址相差2,而不是连续的。