大家好,欢迎来到IT知识分享网。
在编程中经常使用字节对齐来管理分配的内存,需要字节对齐的根本原因在于CPU访问数据的效率和存储空间的使用率问题。例如,一个处理器一次总是从存储器中取出4个字节的数据。如果所有的int类型(这里默认int类型占4个字节)数据的地址对齐成4的倍数,那么就可以用一个操作来读或写int型的数据了。否则,我们可能需要执行多次操作来实现一个int型数据的访问,因为数据可能被分放在几个4字节的存储块中,这样效率会明显降低很多。
总体而言,字节对齐满足如下简单规律(其余的以此类推):
2字节对齐:要求地址为2, 4, 6, 8…,二进制地址的最后一位为0(2的1次方)
4字节对齐:要求地址为4,8,12,16…,二进制地址的最后两位为0(2的2次方)
上述是字节对齐的简单描述,相信有过C编程经验的同学肯定是一看就明白了。有时候在编程时,要动态分配内存了,为了能充分利用内存空间和数据安全,总是会要求把分配的内存按一定的要求向上或向下对齐,那么这时候该怎么操作呢?
首先看两个宏定义(取自RT-Thread源码)
向上对齐:
#define RT_ALIGN(size, align) (((size) + (align) - 1) & ~((align) - 1))
向下对齐:
#define RT_ALIGN_DOWN(size, align) ((size) & ~((align) - 1))
向上或向下对齐,换个通俗的描述就是
向上对齐:计算size以align为倍数的上界数(15以8为倍数的上界数:16)
向下对齐:计算size以align为倍数的下界数(15以8为倍数的下界数:8)
以上描述,相信大家一看就明白了,那么怎么通过编码实现呢?还是以一个实例来看
向下对齐
例:计算size以align字节向下对齐(int类型,这里定义占4个字节)
int size = 15; int align = 8;
以二进制理解其原理,其实开篇就给出了答案:
8字节对齐:要求地址为8,16,24,32…,二进制地址的最后三位为0,即:align = 8;
size对齐后二进制后三位为:000
xxxxxxxx xxxxxxxx xxxxxxxx xxxxx000
size要得到以上数,是不是与运算下面这个数呢
上面二进制数就是~((align) – 1),该数可以称其为对齐字节的掩码
那么size的运算如下:
size二进制表示:
00000000 00000000 00000000 00001111
按8字节对齐后为
00000000 00000000 00000000 00001000
即:size为8
那么整个运算过程就是下面这个式子,这样就得到了向下对齐的数
((size) & ~((align) - 1))
向上对齐
同理,要向上对齐,用的对齐字节的掩码还是一样:~((align) – 1),只需把size向上扩展一个(align-1)即可,即加上(align-1)
(((size) + (align) - 1) & ~((align) - 1))
这里可以理解下,加align-1是为了向上补齐,找出上界,看是否满align个字节
这里有的同学可能要问了,怎么不是加align,而是align-1呢?
还是举个例子:align = 8
如size=16,8字节对齐的上界数就是16,此时加上align-1是23,运算后还是16,解释如下:
16原本就是8的倍数,余数为0,向上扩展align-1个字节后,不满一个align大小,所以对齐后还是16,如果是向上扩展align,就直接加了一个align大小,显然不对
如size=18,8字节对齐的上界数为24,此时加上align-1是25,运算后还是24,解释如下:
18不是8的倍数,8字节对齐后,还余2个字节,要求是向上对齐,那么就需要把这2个字节凑个8字节,这时候加align-1,就变成9个字节,满足一个align大小,所以运算的结果就是24
不是加align,而是align-1,显然明白了吧,就是一个数学问题,与求商和余数是一个道理。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/95449.html