Skip to content

Latest commit

 

History

History
39 lines (26 loc) · 1.87 KB

023 - C 中的这串符号是什么意思.md

File metadata and controls

39 lines (26 loc) · 1.87 KB

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); }))
  1. (e):计算 e 表达式
  2. !!(e):两次逻辑否操作。也就是,如果 e == 0,就返回 0,否则返回 1
  3. -!!(e):对上面的第 2 步得到的值置负。也就是,0 的负数还是 0,1 的负数为 -1
  4. struct{int: -!!(0);} --> struct{int: 0;}:根据第 3 步,如果是 0,那么就声明一个结构体,里边定义了一个位域长度为 0 的匿名位域变量,此时编译正常通过
  5. struct{int: -!!(1);} --> struct{int: -1;}:但如果是 -1 的话,位域长度为负数,那编译器就会报错了

为什么不用assert呢?

因为assert是运行期判断,上面的宏是编译期。不过自 C++ 11 起,也支持静态断言了,可以参考 static_assert