所谓“对齐”
最近在家重温一个视频教程时看到了“对齐”概念,这两个字好像老师上课也有提到过。对于一个词汇,我喜欢先从字面意思入手。为此我查了 一下牛掰的《现代汉语词典》,她是这么说的——对齐:1.使两个以上事物配合或接触得整齐。2.将[两个或更多的机器部件,尤指应互相平行或成行的部件]排到正确的位置或方向。这个应该就是生活中的对齐,就像军训的时候,教官常说,前后对齐,左右十公分云云。那么计算机中的对齐又是怎么回事呢?
“现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。”这是度娘的解释,打个比方来说,现在每列有可以容纳8个人,我现在有一组6人,一组4人,在第一列中放置第一组6人后,我将第二组的4个人不是紧接在第一组的6个人之后,而是令起一组,让它到第二列去,这就是一种简单的对齐,这也是计算机中内存对齐的原理,而这个8就是一个标准,一般叫做对齐系数,每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数),其实就是一个标准,和学习数据结构课程中什么“平衡因子”之类的概念一样,知道是个标准就行。(为了获取更直观的概念,我找到了“计算机组成原理”课程中的一张图,a可以认为是不采用对齐,而b则是使用对齐后计算机内存分配的结果。)

那么问题来了,为什么要使用对齐这种方法呢?固然美观,但我们是看不到的,其实对齐很大程度上是以空间换效率的一种做法。我们知道,各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况, 但是最常见的是如果不按照适合其平台的要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为 32位)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低 字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。就像一个编制,我们需要有一个标准,比如小明和小花关系非常好,如胶似漆,缠缠绵绵,他们俩在编制上可以认为是一个整体啊,而你要把小明分到第一组最后,把小花分到第二组第一个,那岂不是很不方便他们互相传情达意么?
其实,对齐的工作计算机一般都自动为我们做了,以至于我们经常不会感觉到它的存在。我们可以用C语言的结构体来做个实验。比如


这段简单的代码,你可以会以为结果是9,看到结果傻了吧?但没错,由于计算机的自动对齐机制,以4为编制更适合这个结构体的管理和读取,我们的char型就空空占据了4个byte的容量。
要改变这种情况其实非常简单,只要使用预编译指令#pragma pack (value)来告诉编译器,使用我们指定的对齐值来取代缺省的。比如

问题就解决啦!(当然好像也没什么大不了的。)关于对齐,个人认为如果不是喜欢琢磨的话,知道这么回事就行了,当然如果要成为大神,对计算机内存的分配自然要有很深的造诣。
(初次发文,请多指教!)
--Kris于娄底
2015.1.28

浙公网安备 33010602011771号