将地址4字节与8字节边界对齐

时间:2017-08-04 02:04:33

标签: c bit-manipulation

对于我正在处理的程序,我需要将地址四舍五入为距离最近的8字节边界4个字节。也就是说,必须以这样的方式修改地址,使得它们以0x4或0xC结束并且大于或等于它们的当前值。每个地址都是64位整数,指向内存中的单个字节(sizeof(*addr) = 1)。地址保证是无符号的。

我知道可以使用以下代码片段找到最接近的8字节边界,简单的答案就是简单地将0x4添加到该值,但是,这会导致一些高估值的问题。

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

例如,假设我们的地址为0x500B。我想要对齐的值是0x500C,但是如果我们对齐最近的8字节边界(0x5010)然后添加0x4,我们以0x5014结束。这会跳过8个字节,我不想跳过它。

我希望能够使用类似于我在此处提供的8字节对齐宏的简单宏来执行此操作。任何帮助将不胜感激,谢谢!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:-1)

  

需要将地址四舍五入为距离最近的8字节边界4个字节

给定addr是一些整数类型,如(u)intptr_t,具有非负值,或者地址可转换为1:

// 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的更高级别目标。