Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6267653
  • 博文数量: 2759
  • 博客积分: 1021
  • 博客等级: 中士
  • 技术积分: 4091
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-11 14:14
文章分类

全部博文(2759)

文章存档

2019年(1)

2017年(84)

2016年(196)

2015年(204)

2014年(636)

2013年(1176)

2012年(463)

分类: 嵌入式

2013-05-30 10:34:51

问题一:为什么32位CPU只能读取字长(4字节)倍数的地址
答: 因为32位计算机的存储系统通常使用4组存储体,存储一个字长(4字节)数据时采用分体存储方式,即4个存储体各存储1个字节,且低二位(A0和 A1)地址线未用作选址,因而CPU在寻址时只能寻到以字长(4字节)为倍数的地址。同理,16位计算机系统普遍采用两组存储体(奇/偶)分体存储数据, 且低一位(A0)地址线未用作选址,从而导致基于这种设计的CPU只能寻到以2为倍数的地址。

问题二:什么是“自然对齐”?
答:如果一个数据的地址是它类型长度的整数被,那么这个数据就是“自然对齐”的。

问题三:为什么如果多字节型数据不对齐会浪费额外的CPU时钟?
答: 以32位系统为例,假设一个int型数据的地址是0x0004,由于它是对齐的,即CPU可以寻到0x0004这个地址,所以CPU可以一次性将 0x0004 - 0x0007这4个字节的数据取出或存入,但如果它的地址是0x0001,由于CPU在它附近只能寻到0x0000和0x0004这两个地址,所以需要分 别从这两个地址取出数据后拼接得到目标数据。

问题四:为什么定义结构体时,要在末尾用空字节将该结构体长度填充至“长度最大的成员”的长度的整数倍?
答:在接连定义多个结构体对象(或定义结构体数组)时,如果结构体没有自然对齐的话,会导致后续很多结构体内多字节型成员的地址不能满足“自然对齐”,下面举两个例子对比说明。
例一:
struct
{
    long k;        //4字节
    char a[5];    //1字节 * 5 = 5字节
    char pad[3];//1字节 * 3 = 3字节
}                        //该结构体长度为12字节,满足最长成员类型(long)长度(4字节)的整数倍
    假设定义一个拥有2个元素的结构体数组,且首成员long的偏移为0,那么这两个元素内成员的偏移为:
    元素1_long: 0
    元素1_a: 4
    元素1_pad: 9
    元素2_long: 12
    元素2_a: 16
    元素2_pad: 21
    *元素3_long: 24
    由此可见,结构体自然对齐时,定义多个结构体时各自成员必将自然对齐,下面再看一个例子。

例二:
struct
{
    long k;        //4字节
    char a[5];    //1字节 * 5 = 5字节
}                        //该结构体长度为9字节,不满足最长成员类型(long)长度(4字节)的整数倍
    同样假设定义一个拥有2个元素的结构体数组,且首成员long的偏移为0,那么这两个元素内成员的偏移为:
    元素1_long: 0
    元素1_a: 4
    元素2_long: 9    //未自然对齐
    元素2_a: 13

    在这个例子里,结构体的长度没有被填充至long型长度的整数倍,这导致了结构体数组中第2个元素中的long型成员不满足自然对齐条件(即第2个数组元素没有自然对齐),这里元素2_long的内容存放在 0x0009 - 0x000c这4个字节的空间内,但CPU在它附近只能寻址0x0008、0x000c这两个地址,其对应的字长空间分别为0x0008 - 0x000b和0x000c - 0x000f,这就需要分别从0x0008和0x000c两个地址取数据后拼接得到0x0009处的long型数据。
    这就是对结构体型之所以那样补足长度的原因了。

问题四:如果结构体含double型成员,是对该结构体长度填充至字长倍数还是双字长倍数?
答:我个人认为对x86系列CPU来说,填充至字长倍数即可(32位的话对应是4字节对齐),且gcc在这种情况下是这样默认的。至于网上说按8字节对齐的资料,观察后发现它们都交代了诸如“比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始”这样的前提。所以个人推测“将长度填充至长度最大的成员的长度的倍数”这条规则是充分考虑跨平台移植性而定下的,在x86系列平台最长按字长的倍数对结构体类型进行填充即可。


后记:
    不得不承认,对于第四个问题我还是心存疑惑,真心希望能得到大家的指教。
阅读(1301) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~