字节对齐提高存取速度

编译过程中c++编译器为了提高存取速度,设置了在存储格式上的字节对齐。
 一、概念 
   
   对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的。
   注意32位cpu一次读取32位(由于8位编址,也就是读取4个地址的数据,16位编址的话就只读2个地址数据)
  二、为什么要字节对齐
   
   需要字节对齐的根本原因在于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上就不会出现错误,只是效率下降。
------------------------------------------------
1.为什么设置字节对齐能提高存取速度
------------------------------------------------
答:主要是因为现代计算机都使用了Cache。
    Cache可以看成一些可以用非常快的速度进行访问的临时内存。但是Cache的容量不大,比如一般一级Cache只有几K到几十K,二级Cache只有几百K到几M.这个同数G的内存相比,是比较小的。
    但是CPU访问内存非常慢,所以硬件会将平时经常使用的内容存放到Cache里面。Cache是通过一些Cache Line来组织的,每一条Cache Line一般包含16个字节,32个字节或64个字节等。 比如某个计算机一级Cache的Cache Line长度是32个字节,那么每段Cache Line总是会包含32个字节对齐的一段内存。
   现在有一个4字节的整数,如果它的地址不是4字节对齐的,那么就有可能访问它的时候,需要使用两条Cache Line,这增加了总线通讯量,而且增加了对Cache的使用量,而且使用的数据没有在Cache里面(这时需要将数据从内存调入Cache,会非常慢)的机会会增加,这些都降低了程序的速度。

------------------------------------------------
2.字节对齐过程分析
------------------------------------------------
答:在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的对齐方式(vc6.0 32位系统)
类型           对齐方式(变量存放的起始地址相对于结构的其实地址的偏移量)
char           偏移量必须为sizeof(char)即1的倍数
int            偏移量必须为sizeof(int)即4的倍数
float          偏移量必须为sizeof(float)即4的倍数
double         偏移量必须为sizeof(double)即8的倍数
short          偏移量必须为sizeof(short)即2的倍数

    各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对齐方式调整位置,空缺的字节vc会自动填充。同时vc为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。
    以你的情况为例:
struct Mystruct1
{
   int a;
   bool b;
   bool c;
}
    为上面的结构分配空间的时候,vc根据成员变量出现的顺序和对齐方式,先为第一个成员a分配空间,其起始地址跟结构的起始地址相同(偏移量为0,刚好为sizeof(int)的倍数),该成员变量占用sizeof(int)=4个字节;接下来为第二个成员b分配空间,这时下一个可以分配的地址相对于结构的起始地址的偏移量为4,是size(bool)=1的倍数(注意:sizeof(BOOL)=4;sizeof(bool)=1),所以把b存在在偏移量为4的地方满足对齐方式,该成员变量占用1个字节;接下来为第三个成员c分配空间,这时下一个可以分配的地址相对于结构的其实地址的偏移量为5,是sizeof(bool)的倍数,所以c存放在偏移量为5的地方满足对齐方式。
    这时,所有的成员变量都分配的空间,总空间的大小为4+1+1=6,不是结构的字节边界数(即结构中占用最大空间的类型所占用的字节sizeof(int)=4)的倍数,所以需要填充2个字节,以满足结构的大小为sizeof(int)=4的倍数。这时结构占用的内存大小为4+1+1+2=8。

同样的道理
struct Mystruct1
{
   bool a;
   int  b;
   bool c;
}
的分配方式为:
    第一个成员变量a占用1个字节,相对于结构的起始地址偏移量为0,满足对齐方式;第二个成员变量b占用4个字节,下一个可用的地址的偏移量为1,不是4的倍数,需要补足3个字节才能使偏移量为4(满足对齐方式),因此vc自动填充3个字节,b存放在偏移量为4的地址上,它占用4个字节。第三个成员变量c占用1个字节,下一个可用的地址为8(满足对齐方式),所以存放在偏移量为8的地址上;所有成员都分配了空间4+4+1=9,不是结构的字节边界数(sizeof(int))的倍数,所以填充三个字节以满足结构的大小为sizeof(int)的倍数,这样总的空间大小为4+4+4=12。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huangleijay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值