对齐地址从一个8字节的边界4个字节

问题描述:

对于我正在处理的程序,我需要将地址四舍五入为距离最近的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 chux

有时它有助于向后看问题。

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

需要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