什么是" - !!"在C code吗? [英] What is ":-!!" in C code?

查看:190
本文介绍了什么是" - !!"在C code吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我碰上了这个陌生的宏code在<一个href=\"https://github.com/torvalds/linux/blob/ff2d8b19a3a62559afba1c53360c8577a7697714/include/linux/kernel.h#L677-L682\">/usr/include/linux/kernel.h:

  / *强制编译错误,如果条件为真,还会产生
   结果(值0和size_t类型),因此,可以使用前pression
   例如在结构初始化(或在前所未有其他逗号前pressions
   不允许)。 * /
#定义BUILD_BUG_ON_ZERO(E)(的sizeof(结构{INT: - !!(E);}))
#定义BUILD_BUG_ON_NULL(E)((无效*)的sizeof(结构{INT: - !!(E);}))

这是什么: - ?!!


解决方案

这是,实际上,办法来检查前pressionË是否可以评价为0,如果没有,构建失败

宏是有些名不副实;它应该像 BUILD_BUG_OR_ZERO ,而不是 ... ON_ZERO 更多的东西。 (已经有 关于这是否是一个令人困惑的名字

您应该阅读前pression是这样的:

 的sizeof(结构{INT: -  !!(E);}))


  1. (E):计算前pression 电子


  2. !!(E):从逻辑上否定了两次: 0 如果 Ë== 0 ;否则 1


  3. - !!(E):数控否定: 0 如果 Ë== 0 ;否则 1


  4. 结构{INT: - !!(0);} - &GT;结构{INT:0;} :如果是零,那么我们宣布与具有宽度为零匿名整数位域的结构体。一切都很好,我们继续正常。


  5. 结构{INT: - !!(1);} - &GT;结构{INT:-1;} :在另一方面,如果它的不是的零,那么这将是一些负数。声明任何位域的的宽度为编译错误。


所以我们会以风与具有在结构宽度0位域,这是很好的,或负宽度,这是一个编译错误位域。然后我们采取的sizeof 的领域,使我们得到了一个为size_t 与适当的宽度(这将是零的情况下其中,电子为零)。


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

这里

keithmo的回答具有良好的响应:


  

这些宏实现编译时的测试,而断言()是一个运行时测试。


分毫不差。你不想来检测可能已经陷入早些时候在运行时在你的内核问题的!它的操作系统的关键部分。到任何可以在编译时被检测到的程度问题,那就更好了。

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); }))

What does :-!! do?

解决方案

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.

The macro is somewhat misnamed; it should be something more like BUILD_BUG_OR_ZERO, rather than ...ON_ZERO. (There have been occasional discussions about whether this is a confusing name.)

You should read the expression like this:

sizeof(struct { int: -!!(e); }))

  1. (e): Compute expression e.

  2. !!(e): Logically negate twice: 0 if e == 0; otherwise 1.

  3. -!!(e): Numerically negate: 0 if e == 0; otherwise -1.

  4. 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.

  5. 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).


Some people have asked: Why not just use an assert?

keithmo's answer here has a good response:

These macros implement a compile-time test, while assert() is a run-time test.

Exactly right. You don't want to detect problems in your kernel at runtime that could have been caught earlier! It's a critical piece of the operating system. To whatever extent problems can be detected at compile time, so much the better.

这篇关于什么是&QUOT; - !!&QUOT;在C code吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆