c语言中结构体内存对齐细致讨论

声明:本文有参考:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html是在此文章上做相对简短的总结:

 

这里需要声明:我的编译器默认的对齐是4个字节(后面会阐释为什么字节对齐会默认),这系统是32位的。

判断方法一:

首先看下面两个结构体:

struct A{
   char c1;
   int i;
   short s;
   int j;
}a;

struct B{
   int i;
   int j;  
   short s;
   char c1;
}b;

他们的长度分别为:16个字节,12个字节;

我首先在阐释下这个结果的得来:

//对这两个结构体细致分析阐释/

对于A结构体:

       对于结构体A,我们第一眼看去,它的长度是11个字节(是不是呢.....但这是错的...),首先看下A结构体中定义成员变量的顺寻,依次为char、int、short、int,,那么我们就可以提前在我们脑海中下个定义:当前一个类型变量本身占得字节数小于后一个类型变量字节数时,需要在前一个字节用到系统给的字节对齐。  那么这个定义是什么意思呢:

             定义阐释(我自己认为的,仅供参考):   char占一个字节,而其后int占4个字节,所以前一个变量c1就应该用到系统给的字节对齐原则(ok........有人会问到如果此时是一个字符数组会怎么样呢,我会告诉你,同样需要用到系统的字节对齐,,因为,我们看的是单个成员)(这里系统字节对齐是4个字节)。

    怎样用字节对齐:但变量需要用到字节对齐时,补字节对齐的整数,如当前占2字节,系统自己对齐默认为4,那么,需要在当前变量后面添加2个字节的内存空间

   ok............做完上面的想法后,后面的工作就好做了(我们把结构体其实设为0):c1占一个字节即占位为0,由于需要用到系统字节(4个字节)对齐,需要在其后填充3个字节的内存空间,即i的其实位置就为4,由于i占四个字节,所以s的起始地址为8,由于s占用2个字节,需要用到系统字节对齐,因而,j的起始地址为12,j的结束地址15,因而总共占用16个字节,然后和,该结构体中成员中最长字节(为4个字节)的对齐,16对4取整...因而得到为16个字节。

 

注意这里有个细节:

如果有个double类型的插在中间会怎样呢,double是8个字节的,二系统默认是对齐是4个字节,因而,会将double切割开,因而在double前面的变量,按照后面是4个字节的来处理(这个在文章最后我会举例子详细描述),在做完所有的内存偏移关系后,需要注意,该结构体内的长的字节数要和系统默认的对齐字节数(4个字节),最对比,取较小者,来,完成最后的对齐。

 

对于B结构体:

     i占四个字节,不用系统字节对齐,j占四个字节,补用系统字节对齐,s占两个字节,不用系统字节对齐,c1占一个字节,不用系统字节对齐,总共11个字节,然后再取该结构体中占用字节最长(4个字节)的取字节对齐,11对4对齐,得到12....

 

/对这两个结构体细致分析阐释//

采用系统字节对齐时:会浪费cpu的时间,变相的出现程序运行时间变长...........,因而,采取B结构体的定义,既节约空间又节约时间(推介)

 

上面讨论了,对于连个简单结构内存对齐的讨论,其实,可以根据这两个结构体,以及我的分析,拓展到其他复杂的结构体中应用。

 

为什么系统有默认的的字节对齐:

数据对齐不是内存结构的一部分,而是CPU结构的一部分。当CPU试图读取的数值没有正确的对齐时,CPU可以执行两种操作之一:产生一个异常条件;执行多次对齐的内存访问,以便读取完整的未对齐数据,若多次执行内存访问,应用程序的运行速度就会慢。在最好的情况下,是两倍的时间,有时更长。

 

对于结构体对齐总言之:先系统,后结构体成员最长对齐。

下面还用一个对于对齐的自己设定:

#pragma pack(4)       // 这里也可以是#pragma pack(push,4)
struct s1
 
{
 
char a;
 
long int d;
 
double c;
 
};
 
struct s2
 
{
 
char a;
 
long int d;
 
double c;
 
char e;
 
};
#pragma pack(4);//表示在系统字节对齐完了之后,需要对比成员最长占用字节和4字节比较,用较小者再来字节对齐
 
 这一次的到结果是A占用的字节数为16,但B占用20个字节:
这是因为按照之前说的先把系统对齐后,B占用17个字节,然后再和4(成员最长8个字节,和4比较,取4)取字节对齐,得到20个字节。
 
 
判断方法二:
 

首先要确定,结构体成员的每个字节大小,如果有大于系统默认的字节对齐大小,那么取系统的默认大小(4个字节)

核心思想:前一个位置的偏移量能够整除后一个变量类型的字节大小,如果不能,需要在前一个变量的偏移位置填充内存,增加偏移量,使得该偏移量能够整除后一个变量类型字节大小---这句话什么意思呢:下面详细描述

 

以下面这个结构体来举例描述:

Struct stu{

int a;

char b;

short c

double d;

char e;

}s1;

 

计算:a4个字节,b本身是一个字节,但是当前其偏移位置为5不能整除short的字节大小,因而需要在b后填充一个字节,即short开始位置为偏移量是6的位置,short本身是2个字节,也就是现在偏移量为8,能够被后一个double字节对齐(因为其大于系统默认的4个字节,因而,double会分为两个4个字节,因而,实际上这里short对应的后一个是4个字节),当double完了之后偏移量是16,1后一个c1个字节,6%1==0,满足对齐,即当前偏移位置是17,由于需要和4对齐,因而需要在其后填充3个内存的字节

 

以上阐释仅供参考....................................................

 

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值