详解linux下C语言结构体对齐(内存对齐问题)

来源:互联网 发布:mac桌面下方白条 编辑:程序博客网 时间:2024/05/20 03:42

详解C语言结构体对齐(内存对齐问题)

 

 

 

  C语言结构体对齐也是老生常谈的话题了。内容虽然很基础,但一不小心就会弄错。我在刚开始接触的时候也会是很迷糊,通过编译器运行的结果总是和自己的不一样,使自己很苦恼。在网上查了很多的资料,但是说的都很迷糊,但是内存对齐是怎么回事呢?我将网上所说的东西和自己的了解总结一下,其实理解后是非常简单的东西。

首先说一下内存对齐的原则(测试基于linux fedora8)     

原则1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。      

原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)      

原则3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。     

 这三个原则具体怎样理解呢?我们看下面几个例子,通过实例来加深理解。    

 例1:struct A

{

short a1;

short a2;

short a3;

};  

struct B

{                   

long a1;                  

short a2;                  

};            

sizeof(struct A) = 6; 这个很好理解,三个short都为2。

sizeof(struct B) = 8; 这个比是不是比预想的大2个字节?long为4,short为2,整个为8,因为原则3。结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐

运行结果图如下:



 

     例2:

struct A

{                   

int a;                   

char b;                   

short c;                   

};           

 struct B

{                   

char b;                   

int a;                   

short c;                   

};        

 sizeof(struct A) = 8; int为4,char为1,short为2,这里用到了原则1和原则3。         

sizeof(struct B) = 12; 是否超出预想范围?char为1,int为4,short为2,怎么会是12?还是原则1和原则3。

 大家可能一个规则会用但是将原则结合起来就有点犯迷糊了,下面写一下内存的布局。                  a                  

 A的内存布局:1111,     1*,       11         

  0123,    45,      67   

 

其中星号*表示填充的字节

 

那为什么5为1个*号呢?为什么不继续将c的数据填充呢?

这就是用到原则1的地方(第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始),因为5不能被2(c的字节数,c为short为两个字节)整除,换句话说就是起始位置要从该成员大小的整数倍开始其起始位置要为2的倍数,就是原则1c的后面没有补充,因为b和c正好占用4个字节,整个A占用空间为4的倍数,也就是最大成员int类型的倍数,所以不用补充。

 

           B a c

B的内存布局:1***,     1111,   11**  

              0123,    4567,  89,10,11

     B中,b是char为1,b后面补充了3个字节,因为a是int为4,根据原则1,起始位置要为4的倍数,所以b后面要补充3个字节。c后面补充两个字节,根据原则3,整个B占用空间要为4的倍数,c后面不补充,整个B的空间为10,不符,所以要补充2个字节。 

运行结果如下图:



 

   再看一个结构中含有结构成员的例子:        

例3:struct A

{                      

int a;                      

double b;                      

float c;                     

};                 

struct B

{                      

char e[2];                      

int f;                      

double g;                      

short h;                      

struct A i;                     

};         

sizeof(struct A) = 24; 这个比较好理解,int为4,double为8,float为4,总长为8的倍数,补齐,所以整个A为24。

A的布局为:

   a              b       c

1111* * * *, 11111111, 1111 * * * *

 

 

 sizeof(struct B) = 48; 看看B的内存布局。  

 

                e       f         g        h                              

B的内存布局:11* *,   1111,   11111111, 11 * * * * * *,        

i

1111* * * *, 11111111, 1111 * * * *      i其实就是A的内存布局。i的起始位置要为24的倍数,所以h后面要补齐。把B的内存布局弄清楚,有关结构体的对齐方式基本就算掌握了。     

 

 

2 0
原创粉丝点击