为什么要使用 !!(condition) 而不是 (condition)?

35
我曾经看到过一些人在条件语句中使用了两个感叹号。
#define check_bit(var, pos)       (!!((var) & (1 << (pos))))
#define likely(x)       __builtin_expect(!!(x),1)
#define unlikely(x)     __builtin_expect(!!(x),0)

这里是我能找到的一些例子。

使用!!(condition)是否比使用(condition)有任何优势?


2
还可以参考这个这个这个等等。 - devnull
哦,抱歉! - A Person
@Siidheesh 这取决于你的搜索方式,我的初始搜索也没有找到它们,但稍作修改后就找到了。我个人认为,与其他重复帖子相比,没有一个能像我发现的 kernel newbies 线程那样准确地解决问题,所以这个信息可能是值得的。此外,Keith 的解释也比大多数重复帖子中的解释更好,但他通常总是写出很棒的答案。 - Shafik Yaghmour
是的,搜索双重否定就解决了问题。 - A Person
4个回答

33

如果你应用 !! 的变量不是一个布尔类型(即0或1),那么它将把该值规范化为01

关于__builtin_expect,这个内核新手线程讨论了这种符号,并且其中一篇回复解释了(重点在我这里):

__builtin_expect的签名是:

http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html)是:

long __builtin_expect (long exp, long c)

请注意,exp参数应为整型表达式,因此没有指针或浮点类型。双重否定自动处理从这些类型到整型表达式的转换。通过这种方式,您可以简单地编写:likely(ptr)而不是likely(ptr! = NULL)。

参考C99中,bool宏扩展为_Booltrue 扩展为1false扩展为0。详细信息请参见草案标准第7.16布尔类型和值

逻辑否定在6.5.3.3 一元算术运算符的第5段中描述:

逻辑否定运算符!的结果是0,如果其操作数的值与0不相等,则为1。如果其操作数的值与0相等,则结果为1。结果具有int类型。表达式! E等效于(0 == E)。


6
应用于任何标量的一元逻辑非运算符!,如果它的操作数为非零,则产生int0,如果操作数等于零,则产生1。引用标准的说法是:

表达式!E等同于(0==E)

!应用两次于相同的标量值会产生一个结果,如果该值为假则结果为假,如果该值为真则结果为真,但结果分别被规范化为01

在大多数情况下,这并不必要,因为任何标量值都可以直接用作条件。但在某些情况下,您确实需要一个01值。

在C99或更高版本中,将表达式转换为_Bool(或者如果您有#include <stdbool.h>,则转换为bool)具有类似的行为,并且可能被认为更清晰。但是(a)结果的类型为_Bool而不是int,(b)如果您正在使用不支持_Bool的预C99编译器并且已定义自己的bool类型,则它将无法像C99的_Bool那样运行。

4
我能看到的最大问题是,它将强制(或规范化)该值为10 (布尔值),而不管xvar表达式如何扩展(例如chardoubleint等)。

2

将其转换为布尔值,有时可能会很有用。


1
这是C语言而不是C++ - 没有布尔类型。 - Chris Hayes
1
如果你包含了 stdbool.h,在 C 语言中就有 bool - tay10r
1
最初的C语言没有布尔类型,因此人们习惯于使用int来表示布尔值,并将整数(在int中)转换为“布尔值”(在int中)。 - Brendan
3
_Bool 是本地类型。 - arshajii
@arshajii 是的,_Bool 在 C99 中是内置的,抱歉 :) - A Person
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接