__vasz
宏引发的探究首次编辑:24/5/19/18:38
最后编辑:24/5/19/19:06
在研究C语言可变参数函数的实现时,看到了这样一个宏:
#define __vasz(x) ((sizeof(x)+sizeof(int)-1) & ~(sizeof(int) -1))
让人匪夷所思。
这里的x的“实参”是一个类型关键字,返回一个大于sizeof(x)
且能被sizeof(x)
整除的数。
据说是为了实现内存对齐,所有数据都从4的整数倍内存地址开始存。
所以为什么这个宏是这么写的呢?
先看看式子中恒定的后半部分~(sizeof(int) -1)
,sizeof(int)
一般是4(字节),4减1为3,再按位取反,得到0xff...ffc
。看十六进制或许还不太清楚,我们再把它写成2进制:
0b11...1100
再看看式子中前面的部分,用极值分析一下,sizeof(x)
至少为1,1加4减掉1,也就是式子的前半部分最小为4,写成2进制为:
0b00...0100 式子的前半部分
0b11...1100 式子的后半部分
可以看到前半部分最小的情况下,2进制的第3位也与后半部分同为1,再按位与,至少也能够得到4。事实上无论x是其它任何数据类型,2进制的第3位都是1。因为sizeof(x) - 1
最小为0,而又加上了sizeof(int)
,所以整个前半部分最小值为sizeof(int)
(一般为4)。写成2进制数,第3位就是1。
而后半部分的低两位为0,无论前半部分的值是多少,和后半部分按位与之后,低两位都会是0。
而前半部分的第3位始终为1,后半部分的第3位同样也始终为1,所以相与之后,至少都能得到4。
不知道谁想出的这个宏,还挺牛逼的。