结构体字节对齐

来源:互联网 发布:vb 注释符号 编辑:程序博客网 时间:2024/06/03 17:24

引入问题:

最近在做一些网络开发方面的事,首先是客户端A向服务器端B按照之前定义的协议发送一个结构体过去,然后服务器B回复给客户端B另一个结构体,问题就出现了,我用wireshark进行抓包,发现服务器是按照我的预期回复了指定大小的数据包,可是客户端B这边使用相同的结构体进行接收,大爷的,竟然不能正常将数据融合进去,调试打印发现在客户端这边计算出的结构体大小却不是我想要的,总要大两个字节。仔细查阅,才明白这是字节对齐造成的!

概念

对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的。

为什么要字节对齐
   
   需要字节对齐的根本原因在于CPU访问数据的效率问题。假设上面整型变量的地址不是自然对齐,比如为0x00000002,则CPU如果取它的值的话需要访问两次内存,第一次取从0x00000002-0x00000003的一个short,第二次取从0x00000004-0x00000005的一个short然后组合得到所要的数据,如果变量在0x00000003地址上的话则要访问三次内存,第一次为char,第二次为short,第三次为char,然后组合得到整型数据。而如果变量在自然对齐位置上,则只要一次就可以取出数据。一些系统对对齐要求非常严格,比如sparc系统,如果取未对齐的数据会发生错误,举个例:
char ch[8];char *p = &ch[1];int i = *(int *)p;
  运行时会报segment error,而在x86上就不会出现错误,只是效率下降。

想要编译器按照你想的方式来进行字节对齐有个方式,就是在程序里面使用
//告诉编译器,让它在计算结构体大小时按照n个字节对齐#pragma pack(n)

在实际的程序开发中,为了提高数据的读取效率,在内存资源足够的情况下,一般定义数据结构时候,因该考虑四字节对齐,其原因很简单,现在的计算机大部分是32位机,也就是四个字节。在cpu每次执行读取数据时候,则相关处理数据的寄存器/ 累加器均只能处理32位数据,则只能读取(一次)32位数据。有些情况下字节对齐的数据结构,要比非对齐的数据结构上占用更少空间。

对于标准数据类型,它的地址只要是它的长度的整数倍就行了,而非标准数据类型按下面的原则对齐: 
  数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。 
  联合 :按其包含的长度最大的数据类型对齐。 
  结构体: 结构体中每个数据类型都要对齐。

在CSDN上面关于字节对齐方面的讲解已经很多了,我想我再去复述,应该也没得那些大牛总结的清楚。给出两个我觉得说的很详细的大牛的博客链接:

1.http://blog.csdn.net/21aspnet/article/details/6729724
2.http://blog.csdn.net/wangshihui512/article/details/9664145

0 0
原创粉丝点击