C語言分配n位元組對齊記憶體地址

2020-08-11 14:46:04

需求:

分配一段長度爲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