2017-08-04 86 views
1

對於我正在處理的程序,我需要將地址四捨五入爲距離最近的8字節邊界4個字節。也就是說,必須修改地址,使其以0x4或0xC結尾,並且大於或等於其當前值。每個地址是一個64位整數,指向內存中的單個字節(sizeof(*addr) = 1)。地址保證是無符號的。對齊地址從一個8字節的邊界4個字節

我知道最接近的8字節邊界可以通過下面的代碼片段找到,簡單的答案是簡單地將0x4加到該值,但是這會導致一些高估該值的問題。

#define align_8(addr) (((addr) + 7) & (~7)) 

例如,假設我們有地址0x500B。我希望這個對齊的值是0x500C,但是如果我們對齊到最近的8字節邊界(0x5010)然後加上0x4,我們以0x5014結束。這跳過了我不想跳過的8個字節。

我想用一個類似於我在這裏提供的8字節對齊宏的簡單宏來做到這一點。任何幫助將不勝感激,謝謝!

+1

'while(addr%8!= 4)addr ++;'works。其他想法可以避免循環。 – chux

+0

@chux謝謝,我會暫時使用它。 – beeselmane

+1

提示:注意失敗了'addr <4'的解決方案。 – chux

回答

1

有時它有助於向後看問題。

A B C D E F 
5003 5004 +1 4FFE 4FF8 5004 
5004 5004 +0 4FFF 4FF8 5004 
5005 500C +7 5000 5000 500C 
5006 500C +6 5001 5000 500C 
5007 500C +5 5002 5000 500C 
5008 500C +4 5003 5000 500C 
5009 500C +3 5004 5000 500C 
500A 500C +2 5005 5000 500C 
500B 500C +1 5006 5000 500C 
500C 500C +0 5007 5000 500C 
500D 5014 +7 5008 5008 5014 
500E 5014 +6 5009 5008 5014 

觀察:

(A) What you have 
(B) What you want 
(c) Distance A to B 

生成算法添加0 ... 7酌情:

(D) Subtract 5 from (A) 
(E) And (D) with 0xFFFFFFFFFFFFFFF8 to get rid of the 3 LSBs 
(F) Add decimal 12 to (E) 

由於(F)=(B),目標是用這些實現操作:

((Addr - 5) & 0xFFFFFFFFFFFFFFF8) + 12 
+0

注:'〜7'的想法需要補充正確的類型。 '〜7'可能只有0xFFFFFFF8,但地址比32位寬。 – chux

-1

需要MAC進行向上舍入爲關閉最近8字節邊界

鑑於addr的4個字節是某個整數型像(u)intptr_t具有非負值,或地址轉換爲一個:

// Only evaluates `addr` once. 
#define align8_plus4(addr) ((void*)(((uintptr_t)(addr) + 4 - 1)/8)*8 + 4)) 

char *addr_aligned = align8_plus4(addr_unaligned) 

極端情況:
1)0-3作品。
2)(uintptr_t)(addr) + 4 - 1溢出時無法提供正確的答案,因爲沒有正確的答案。


注意:這不是高度可移植的代碼,生成這樣的地址不知道是有效的。然而,應該爲OP的選擇案例工作。便攜式方法會考慮爲什麼需要+4的更高層次的目標。

+1

這個宏不起作用。我已經嘗試了多種上下文,並通過不同的金額給出了不正確的偏移量。例如,22應該導致2的偏移量,然而這個宏產生5的結果。同樣,85應該導致7的結果,但是它會得到4. – beeselmane

+0

@beeselmane代碼修正。 – chux