您的位置:首页 > 其它

关于字节对齐的看法

2012-07-23 04:04 162 查看
  由于CPU的读取内存是以字长为单位的,而内存编址是一字节为单位的,比如一个32位机器,其读取内存一次是4个字节,而并不是一个字节为单位进行读取。因为这个原因,期望编译器变量在编址时要有所调整,以满足最少次数读取原则。

  原始类型:

  对于长度为一个字节的变量,无论其存放的位置如何都可以一次读取内存来获得其值,比如char a ,放在1,2,3,4,都是通过读取1开始的这个字长块内存,再根据字节地址来获取变量a的值,若放在2上,读取第二个字节开的长度为1的内存块。

  同样道理,对于长度为两个字节的变量,那么只要其存放开始地址是偶数,就能通过一次读取内存来获取。对于长度是4的变量,就必须存储在以4的倍数为开始地址的内存块,若不是,则需要CPU进行两次读取,然后再拼凑一次。
  但是,对于长度超过4的类型,比如long long类型,其长度为8,我们可以发现,只要起始位置地址数值时4的倍数同样能满足要求。即 存放起始位置 % 类型长度 == 0 || 存放起始位置 % 4 == 0 。
  我们发现没,所有原始类型都是2的n次方, 如:1,2,4,8,16......同时编译器对所有变量(包括结构类型变量)编址都是字长(4)的n倍。

  结构类型:

  结构类型需要看他字节对齐长度和机器字长。

  笔者VC默认对齐长度是4,32为机器,这意思是重开始位置开始以4为单位划分块,再加入成员变量,能够容下就放入,不能容下就放入下一个块,对于类型长度超过分块长的,就增加块来放入。在结构的末尾,需要补全,使总长度为4n。

  比如,char后跟一个short,那么能够容下,这两个成员将在一个长度为4的块中,要是shrot后再有一个char,同样能够容下,一起放在这个块中。要是short后跟一个int,容不下,所有从下一个块开始放int,要是shourt后更一个double,容不下,放入下一个块,但长度超过4,用两个块来存放。若是长度为6,那么这后面还可以加入两个char哦。

  若对齐长度为2,按2来进行填充和补全。

  当对齐长度超过机器字长,那么按机器字长来进行进行对齐。比如若设对齐长度为8,那么还是进行着以4为对齐长度的对齐。

  通过#pragma pack(n) 和 #pragma pack(pop),来调整对齐长度,一般只需要改为1。当在网络上传输时,不同的机器的默认对齐方式可能不同,接收的buff的解析情况就会有差异。

struct t
{
char a;
int b;
}


  假设接收一个对象t1的buff,指针p指向buff,若发送接收两方都采用同样的对齐!用p->b来获取不会出错,要是发来这个buff的机器使用的长度为1的对齐,而本机用4,将会出错。

  后记:

  OK!总算完全理解了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: