我在 /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 的方法,如果不能,则构建失败。
宏的名称有些错误;它应该更像 BUILD_BUG_OR_ZERO
,而不是 ...ON_ZERO
。 (已经有 occasional discussions about whether this is a confusing name 。)
您应该像这样阅读表达式:
sizeof(struct { int: -!!(e); }))
(e)
:计算表达式e
.
!!(e)
:逻辑否定两次:0
if e == 0
;否则 1
.
-!!(e)
:数值否定步骤 2 中的表达式:0
if it is 0
;否则 -1
.
struct{int: -!!(0);} --> struct{int: 0;}
: 如果为零,那么我们声明一个带有匿名整数的结构体宽度为零的位域。一切都很好,我们照常进行。
struct{int: -!!(1);} --> struct{int: -1;}
:另一方面,如果它不是 零,那么它将是一些负数。用 negative 宽度声明任何位域都是编译错误。
所以我们要么在结构中得到一个宽度为 0 的位域,这很好,要么是一个具有负宽度的位域,这是一个编译错误。然后我们取 sizeof
那个字段,所以我们得到一个具有适当宽度的 size_t
(在 e
为零的情况下将为零) .
有人问:为什么不直接使用assert
?
keithmo's answer这里有一个很好的回应:
These macros implement a compile-time test, while assert() is a run-time test.
完全正确。您不想在运行时检测到您的内核 中可能更早发现的问题!它是操作系统的关键部分。在编译时可以检测到任何程度的问题,那就更好了。
关于c - C 代码中的 ":-!!"是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9229601/