对齐

字节对齐这个概念是C语言中层次 相对较深的一个问题,从理论上来说——引入这个概念纯属找麻烦,我第一次接触到这个问题时的感想就是“天下本无事,庸人自扰之”。不过我们是生活在现实中而不是神话中,所以对齐这个问题还是需要在战术上予以重视的。
对齐的产生是因为计算机的硬件设计,访问奇地址和偶地址是不同的(具体参考微机原理)。这样如果对数据不进行对齐,取数据的时候可能遇到一个数据需要读两次的然后拼凑起来的可能——这样显然大大降低效率,在早期这是无法接受的,于是对齐这个讨厌的东西就产生了。
字节对齐对于内置的固定的数据类型是有默认值的,比如,byte默认1字节对齐,int默认4字节对齐等等,最大的问题出在struct结构上,一个struct结构随着不同的定义,可能sizeof是不同的。
struct aaTag
{
char i;
short j;
int k;
}a;

struct bbTag
{
short j;
int k;
char i;
}b;
然后运行sizeof(a),sizeof(b),结果可能让你大吃一惊,前者答案为8,后者答案为12,这个就是对齐的问题了,这些东西由编译器悄悄的帮你完成了,然后在某个地方让你大吃一惊。
简单来说,大多数默认情况下使用4字节对齐,对齐的原则是结构体中的每个字段需要找到自有对齐方式和指定的对齐方式中较小的那种来进行对齐。我们分析一下上面的两个数据结构,a中i占2个字节(因为short需要从2的倍数的地址开始),j占2个字节,k占4个字节,于是sizeof(a)为8;而b中j占4个字节(因为int需要从4的倍数的地址开始),k占4个字节,然后i还需要占4个字节,所以sizeof(b)就成了12。
这是一个简单的例子,复杂的结构,比如struct中套struct的东西就会更复杂,当然规则还是那样来计算,不过需要递归子struct,一个struct的自由对齐方式是他所有结构中最大的那个。

一般简单的使用中并不产生什么问题,但是,啊,但是,在一段给定的数据memcpy给一个这样的结构体时,你就需要注意了,否则当你使用的时候,会惊奇的发现出现了一些莫名其妙的问题。

这几天在调试手机上的显示界面,公司里的显示使用一个工具把资源自动的变成数据库,然后使用一套API去检索取值,最后送到屏上显示。当这套东西从一个platform移植到另一个platform时出现了问题,显示总是取到错误的值,好一点就是显示不正确,运气不好时就是死机。仔细跟踪后才发现,就是对齐在里面作祟,这个问题没有很好的解决办法,可能最好的办法是统一平台的一些参数——不过现实中这个也很难做到。那么,剩下的就是在编码中有意识的进行对齐,缺省的地方显示的用空闲的byte来填充,这样可以有效的避免这种对齐问题。

你可能感兴趣的:(对齐)