我见过人们使用带有两个'!'的条件子句的代码
#define check_bit(var, pos) (!!((var) & (1 << (pos))))
#define likely(x) __builtin_expect(!!(x),1)
#define unlikely(x) __builtin_expect(!!(x),0)
是我能找到的一些例子。
使用!!(condition)
优于(condition)
是否有任何好处?
答案 0 :(得分:33)
如果您应用的变量!!
不是bool
(零或一个),那么它将规范化该值到0
或1
。
关于__builtin_expect
此kernel newbies thread讨论了符号,其中一个回复解释了(强调我的):
__builtin_expect的签名
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html)是:
long __builtin_expect(long exp,long c)
请注意,exp参数应该是一个整数表达式,因此没有指针 或那里的浮点类型。 双重否定处理来自的转换 这些类型自动为积分表达式。这样,就可以了 写:可能(ptr)而不是可能(ptr!= NULL)。
C99 bool
中的参考宏扩展为_Bool
,true
扩展为1
,false
扩展为{{ 1}}。详细信息在标准草案部分0
布尔类型和值中给出。
5 段落中的7.16
一元算术运算符涵盖了逻辑否定:
逻辑否定运算符的结果!如果其操作数的值比较,则为0 不等于0,1如果其操作数的值比较等于0.结果的类型为int。 表达式!E等价于(0 == E)。
答案 1 :(得分:6)
应用于任何标量的一元!
逻辑否定运算符如果操作数非零,则生成int
值0
,如果操作数相等则生成1
为零。引用标准:
表达式
!E
相当于(0==E)
。
将!
两次应用于相同的标量值会产生如果值为false则为false的结果,如果值为true则为true - 但结果将标准化为0
或{{1}分别。
在大多数情况下,这不是必需的,因为任何标量值都可以直接用作条件。但在某些情况下,您实际上需要1
或0
值。
在C99或更高版本中,将表达式转换为1
(或_Bool
,如果bool
具有相同的行为,可能会被认为更清晰。但是(a)结果是类型#include <stdbool.h>
而不是_Bool
,以及(b)如果您使用的是不支持int
的C99前编译器,并且您已定义了自己的_Bool
类型,它的行为方式与C99的bool
不同。
答案 2 :(得分:4)
我能看到的最大值是,它会强制(或规范化)值1
或0
(这是一个布尔值),无论x
或{的方式如何{1}}表达式展开(例如var
或char
或double
等。)
答案 3 :(得分:2)
它转换为布尔值,有时可能很有用。