我在试着了解这条线是如何工作的。它应该将uint32地址对齐到其最近的8字节对齐地址。
static inline uint32_t
ZBI_ALIGN(uint32_t n) {
return ((n + ZBI_ALIGNMENT - 1) & -ZBI_ALIGNMENT);让我们以n=10和ZBI_ALIGNMENT=8为例。最近的地址应该是16
返回((10 + 8 -1) & -8) = 17 & -8
为什么这应该是一致的呢?
发布于 2021-07-30 18:46:11
这个公式的关键是,只有当ZBI_ALIGNMENT恰好是两个幂的时候,它才是有效的,这并不是什么大问题,因为对齐的要求往往符合这个标准。
正在对齐的数字(也称为2的倍数)二的幂表示所有小于该二次幂的位都被设置为0。只要看几个8位的数字,你就可以轻易地说服自己:
15: 00001111
16: 00010000 <--- aligned to 16
17: 00010001
31: 00011111
32: 00100000 <--- aligned to 16
48: 00110000 <--- aligned to 16假设我们有一个只有16位高或等于16位的掩码,那么对于16的所有倍数,N & mask将是一个无运算,并给出所有其他值的16的前一个倍数。
16: 00010000
mask for 16: 11110000
15 & mask -> 00000000 : 0
16 & mask -> 00010000 : 16
17 & mask -> 00010000 : 16
32 & mask -> 00100000 : 32为了直接得到正确的值,我们可以使用(N + 15) & mask。如果N已经是16的倍数,那么N + 15将接近下一个倍数。否则,它总是会将值“凸”到下一个范围。例如1+15 = 16,16 + 15 = 31等..。这被概括为(N + (DESIRED_ALIGMENT - 1))。
所以剩下的就是如何计算给定对齐的掩码。
方便地,在两个补码表示中(所有有符号整数都必须使用),两个幂的负值正好是我们需要的掩码。
对于8位数,如下所示:
-1 -> 11111111
-2 -> 11111110
-4 -> 11111100
-8 -> 11111000
etc...因此,mask可以简单地计算为-ZBI_ALIGNMENT。
把所有这些放在一起,我们得到:
((n + ZBI_ALIGNMENT - 1) & -ZBI_ALIGNMENT)
https://stackoverflow.com/questions/68595189
复制相似问题