https://stackoverflow.com/questions/9229601/what-is-in-c-code
我在 /usr/include/linux/kernel.h 里遇到了一个奇怪的宏,
/* Force a compilation error if condition is true, but also produce a
result (of value 0 and type size_t), so the expression can be used
e.g. in a structure initializer (or where-ever else comma expressions
aren't permitted). */
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
:-!!
是什么意思?
其实是用来检查表达式 e 是否为 0 的。如果不为 0,编译器就会报错。(其实就是我们常说的静态断言)
这个宏的名字其实起的不好,应该为BUILD_BUG_OR_ZERO
,这里有个相关的讨论:occasional discussions about whether this is a confusing name
下面来分析下上面的宏:
sizeof(struct { int: -!!(e); }))
(e)
:计算 e 表达式!!(e)
:两次逻辑否操作。也就是,如果 e == 0,就返回 0,否则返回 1-!!(e)
:对上面的第 2 步得到的值置负。也就是,0 的负数还是 0,1 的负数为 -1struct{int: -!!(0);} --> struct{int: 0;}
:根据第 3 步,如果是 0,那么就声明一个结构体,里边定义了一个位域长度为 0 的匿名位域变量,此时编译正常通过struct{int: -!!(1);} --> struct{int: -1;}
:但如果是 -1 的话,位域长度为负数,那编译器就会报错了
为什么不用assert
呢?
因为assert
是运行期判断,上面的宏是编译期。不过自 C++ 11 起,也支持静态断言了,可以参考 static_assert