stackoverflow上看到的这个问题,觉得挺有趣,顺手记下来。
楼主提问:
I bumped into this strange macro code in /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); }))
回答是:
This is, in effect, a way to check whether the expression e can be evaluated to be 0, and if not, to fail the build.
用于检测表达式是否为零或者为空,如果是,编译阶段直接报error。注意,是编译阶段,而传统的assert只能解决运行阶段的问题。
解析如下:
You should read the expression like this:
sizeof(struct { int: -!!(e); }))
-
(e)
: Compute expressione
. -
!!(e)
: Logically negate twice:0
ife == 0
; otherwise1
. -
-!!(e)
: Numerically negate the expression from step 2:0
if it was0
; otherwise-1
. -
struct{int: -!!(0);} --> struct{int: 0;}
: If it was zero, then we declare a struct with an anonymous integer bitfield that has width zero. Everything is fine and we proceed as normal. -
struct{int: -!!(1);} --> struct{int: -1;}
: On the other hand, if it isn't zero, then it will be some negative number. Declaring any bitfield with negative width is a compilation error.
So we'll either wind up with a bitfield that has width 0 in a struct, which is fine, or a bitfield with negative width, which is a compilation error. Then we take sizeof
that field, so we get a size_t
with the appropriate width (which will be zero in the case where e
is zero).