C代码中的“:-!!”是什么?

我在/usr/include/linux/kernel.h中遇到了这个奇怪的宏代码:

/*如果条件为true,则强制执行编译错误,但也会生成
结果(值为0,类型为size\t),因此可以使用表达式
e、 g.在结构初始值设定项中(或在其他任何地方使用逗号表达式)
不允许)*/
#在0(e)(sizeof(struct{int:-!!(e);}))上定义构建错误
#在空(e)((void*)sizeof(struct{int:-!!(e);})上定义构建BUG)

什么是:-做什么

实际上,这是一种检查表达式e是否可以计算为0的方法,如果不能,则检查生成是否失败

宏有点命名错误;它应该更像是BUILD\u BUG\u或\u ZERO,而不是…ON\u ZERO。(关于这是否是一个令人困惑的名字,偶尔会有讨论)

你应该这样读:

sizeof(结构{int:-!!(e);}))
  1. (e):计算表达式e

  2. !!(e) :逻辑求反两次:0如果e==0;否则1

  3. -!!(e) :对步骤2中的表达式进行数字求反:0,如果它是0;否则-1

  4. struct{int:-!!(0);}-->struct{int:0;}:如果它是零,那么我们声明一个具有宽度为零的匿名整数位字段的结构。一切正常,我们照常进行

  5. struct{int:-!!(1);}-->struct{int:-1;}:另一方面,如果它不是零,那么它将是一些负数。使用宽度声明任何位字段都是编译错误

因此,我们要么在结构中得到宽度为0的位字段,这很好,要么得到宽度为负的位字段,这是一个编译错误。然后我们取该字段的sizeof,得到一个宽度合适的size\u t(在e为零的情况下,该值为零)


有人问:为什么不直接使用断言?

基思莫在这里的回答有很好的回应:

这些宏实现编译时测试,而assert()是运行时测试

完全正确。您不想在运行时检测到内核中的问题,这些问题可能在更早的时候就被发现了!它是操作系统的关键部分。无论在编译时可以检测到多大程度的问题,那就更好了

发表评论