define
一句话是 :
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
我被告知目的是位对齐。
我想知道它是如何工作的,提前谢谢。
上面的宏只是将 的大小n
与最近的大于或等于sizeof(int)
边界对齐。
a
将值与最近的大于或等于任意边界对齐的基本算法b
是
a
_b
b
。在无符号(或只是正)值的域中,第一步是通过以下流行的技巧实现的
q = (a + b - 1) / b
// where `/` is ordinary C-style integer division (rounding down)
// Now `q` is `a` divided by `b` rounded up
将此与第二步结合起来,我们得到以下结果
aligned_a = (a + b - 1) / b * b
在aligned_a
您获得所需的对齐值。
将此算法应用于手头的问题将得到以下_INTSIZEOF
宏的实现
#define _INTSIZEOF(n)\
( (sizeof(n) + sizeof(int) - 1) / sizeof(int) * sizeof(int) )
这已经足够好了。
但是,如果您事先知道对齐边界是 2 的幂,则可以通过用简单的按位运算替换除法+乘法序列来“优化”计算
aligned_a = (a + b - 1) & ~(b - 1)
这正是上述_INTSIZEOF
宏的原始实现中所做的。
这种“优化”可能对某些编译器有意义(尽管我希望现代编译器能够自行解决)。但是,考虑到上述_INTSIZEOF(n)
宏显然是用作编译时表达式(它不依赖于任何运行时值,除了作为 传递的 VLA 对象/类型n
),以这种方式优化它没有多大意义。
这里有一个提示:
一个常用的方法ceil(a/b)
是:
(a + (b-1)) / b
b * ( (a + b - 1) / b ) = (a + b - 1) & ~(b - 1)
要了解上述原因为何成立,请考虑以下几点:
第一部分(为什么 q = (a + b - 1) / b 产生我们正在寻找的数字):
...请注意,我们希望 q 是 a 中 b 的数量,但向上取整(即,如果整数除法后有余数,则该余数应向上取整为 b,因此 q 增加 1 )。
存在 Q 和 R 使得 a = Qb + R,因此 a + b - 1 = Qb + b - 1 + R。如果我们对 a + b - 1 进行整数除法,我们将得到 Q + (b- 1+R)/b。如果 R 为零,则第二部分将为零,如果 R 不为零,则为 1(注意 R 保证小于 b)。
第二部分(宏):
现在如果 b 是 2 的幂,那么 a + b - 1 除以 b 只是 b 的指数的右移(即 b = 2^n,然后右移 n 位)。
此外,乘以 b 是左移(左移 n 位)
因此结合起来,我们所做的就是将最右边的 n 位清除为零,这是通过屏蔽来实现的:~(b-1) 给我们 1111...111000...0 其中 1 的数量等于 n ( b = 2^n)