需求:
分配一段长度为BUFFER_SIZE个字节的内存,首地址要求n字节对齐
分析:
这个问题的关键是要求首地址按照n字节对齐。为了方便分析,我们以8字节对齐为例
也就是当初始首地址给定为(0,8]之间,我们要将首地址调整到8字节处;当初始首地址在(8,16]之间,我们要将首地址调整到16字节处.....依此类推。总而言之,就是右对齐,与内存地址的增长方向相同。
方案:
为了确定首地址,封装了一个宏,如下:
#define ADDR_ALIGN_BASE 8
#define ADDR_ALIGNED(addr) (((addr) + ADDR_ALIGN_BASE - 1) & (0xfffffff8))
输入addr是一个随意给定的地址,返回一个8字节对齐(右对齐)的地址
总共分为两步:
- 将给定地址加上(8-1)字节,得到一个新地址
- 将新地址和0xfffffff8相与,得到最终的8字节对齐的地址
先解释几个问题:
1.为什么是加上,而不是减去;为什么加上的是7个字节,而不是8字节呢?
加上是和内存的增长方向相同,以避免覆盖掉之前的数据(在此默认给定的addr地址之前的内存空间已经使用,addr地址之后的空间没有使用)
加上7个字节是为了避免空间浪费。举一个极端的例子,比如给定的地址就是8字节处,已经对齐,如果加上8个字节的话最终得到的对齐地址就是16字节处,虽然说也是基于8字节对齐,但是8-16字节处的空间浪费掉了。
2.为什么要和0xfffffff8与?
0xfffffff8转换成二进制就是11111111111111111111111111111000,也就是后面跟着三个零,2的3次方正好是8。最终目的就是得到一个能被8整除的地址。
举例:
为了方便理解,举两个例子说明
1.给定地址为7字节处,要求转换为8字节对齐的地址
第一步,7+(8-1) = 14(0x0000000e)
第二步,(0x0000000e)&(0xfffffff8)= 8
结果为8字节处
2.给定地址为9字节处,要求转换为8字节对齐的地址
第一步,9+(8-1) = 16(0x00000010)
第二步,(0x00000010)&(0xfffffff8)= 0x10(16)
结果为16字节处
ref:
http://www.manongjc.com/detail/10-hgdukjoorgrtexk.html
https://www.jianshu.com/p/eb497ea3f551
https://baijiahao.baidu.com/s?id=1642532556639906097&wfr=spider&for=pc