C/C++ 中所有逻辑运算符(logical operator)中,其操作数(operand)都是以 零 和 非零 去判断假和真的。例如,对一元的逻辑取反(negation)! 运算符而言:
printf("%d\n", !0); // 1
printf("%d\n", !1); // 0
printf("%d\n", !2); // 0 (这个比较不直觉)
printf("%d\n", !!2); // 1 (用 !! 可把任何数值强制变成 0 或 1)
The !
operator performs logical negation. If its argument is non-zero, it results in 0. If its argument is 0, it results in 1.
In C there are no bool
s (not like true
/false
) but it's an int
value. (either 0
or 1
) , !x
is either 1 or 0, So !!x
is a "collapse to 0 or 1 operator" in the sense that any non-zero number is mapped to 1, and 0 stays as it is. This can be useful on occasions.
In C++, !x
is a bool
type, So !!x
is a "collapse to false or true operator" in the sense that any non-zero number is mapped to true
, and zero is mapped to false
.
!! is not an operator. It’s just the ! operator twice
The first negation converts the data (whatever it data type it may be) to a bool. The second negation changes the boolean again to give the desired result.
双非运算符(!!) 使用两个 ! 运算符。(C++/C#/Javascript)第一次取反操作将操作数转换成与其相反的 bool 值,第二个取反操作将操作数反转回来,这时就成为了明确的 true 和 false 的值。
!!false === false
!!true === true
!!0 === false
!!1 === true
!!-1 === true // -1 is truthy
!!null === false // null is falsy
What does Double Logical Not Operators (!!) Mean in C
Sometime you will see the following statement in C/C++ source code:
bool isKeepGoing = !!func();
You may wonder, “Why the author uses double logical not (!!
)? Convert to the opposite boolean value, and convert back? It doesn’t make any sense to me…”
Well, what the author really wants to do is converting the return value of the func
function to a boolean value: The first logical operator will convert whatever return value to the opposite boolean value, and then the second logical operator will convert the opposite value back.
To be honest, this is a horribly obscure way to do the boolean type conversion. Nearly 99.999% of C/C++ programmers won’t understand what the statement really means. They can understand the syntax, but they cannot understand why. “Is there any trick behind this statement?”
Unless you want to obfuscate your source code, please, please don’t use this kind of statement. Instead, you can use normal casting to clearly express what you want to do:
bool isKeepGoing = (bool)func();