使用双重逻辑非(!!)运算符感到困惑

37
我有一些C++代码,其中广泛使用了!!。我有点困惑,因为据我所知!!不是一个单独的运算符,而是两个相邻的!。这意味着!!foofoo是相同的。
是否存在任何情况或原因,使得使用!!有实际意义?我在想它是否可能具有位运算的含义?因此,您首先对foo执行某些位运算,然后对结果执行!?但我似乎记得!并没有被用作位运算符,并且似乎也找不到任何参考资料告诉我它是。据我所知,仅用作逻辑运算符,在这种情况下 !!foo == foo

5
可以写成x+++++y+1,但这是个不好的主意。 - msw
@GrahamBorland 现在我要去那里,将其标记为此问题的重复。 - Alvin Wong
您可能也想阅读:C语言中的!!是什么? - Grijesh Chauhan
@msw 不行。在两个序列点之间多次修改是未定义行为。 !! 是完全定义的,对应于触发安全布尔转换运算符。这对于 optionalvariant 或任何智能指针特别有用。 - v.oddou
5个回答

56

它不是简单的双重否定。例如,如果你有x == 5,然后使用两个!运算符(!!x),它将变成1 - 因此,它用于将布尔值规范化为{0, 1}范围内。

请注意,您可以使用零作为布尔值假,非零作为布尔值真,但您可能需要将结果规范化为0或1,这时!!就很有用。

这与x != 0 ? 1 : 0相同。

另外,请注意,如果foo不在{0, 1}集合中,则这不会成立:

!!foo == foo

#include <iostream>

using namespace std;

int main()
{
        int foo = 5;

        if(foo == !!foo)
        {
                cout << "foo == !!foo" << endl;
        }
        else
        {
                cout << "foo != !!foo" << endl;
        }



        return 0;
}

打印 foo != !!foo


这个可能有哪些潜在的使用场景? - Koushik Shetty
3
假设你有一个地方存储了一个布尔值,可能是在一个二进制位里面,它的值为1或0。如果你想检查该值是否等于5(也就是判断它是否为真),你可以把这个5转换成1。请注意,这并不改变原有含义。 - inquam
bool x = !0; // 真 bool x = !-15 // 假 int i = x; 看看这个 - mtsiakiris
4
稍微正式一点,它的结果是“真”。类型为“bool”的值为“真”和“假”。在算术上下文中,它们分别转换为“1”和“0”。 - Pete Becker
1
我曾在编译器上使用过这种技术,当我将int隐式转换为bool时,编译器会发出警告(性能警告:值将被转换为0或1)。我的选择是进行C风格的bool转换(我认为这是一个不好的习惯),使用0 != v(之后的?1:0是多余的),这会创建操作顺序的歧义,强制使用括号(至少要清楚地表明正在发生什么),或者使用static_cast<bool>(v),这太冗长了。!!将可以隐式转换为bool的类型转换为bool,而不会发出警告,并作为一元运算符(因此与之紧密绑定)。 - Yakk - Adam Nevraumont
!!cond 和 !!(cond) ? 之间有一些差别。 - magrif

9

它可以用作将foo转换为布尔表达式的速记。您可能希望将非布尔表达式独占地转换为true或false,出于某种原因。

foo = !!foo会将foo转换为1(如果它是非零的),并将其保持为0(如果它已经是0)。


4
如果 foo != 0,那么 !!foo == 1。这基本上是一种将其转换为布尔型的技巧。

2
1 不是 bool。它是一个 int - Kerrek SB
2
@Kerrek SB 我知道,我指的是实际值。 - Avidan Borisov

3
如果foo不是bool类型,那么!!foo将会是bool类型。因此!!foo可以是1或0。

1
01int类型,而不是bool类型。我们在谈论C++,也许你把它和C混淆了? - Kerrek SB
你说得对。我应该说真或假。 :) - Tobias Müller

2

这种技术用于在布尔上下文中对变量进行安全评估。如果您将非布尔变量(具有不同类型)转换为bool(operator bool()),则它们可能以不希望的方式参与布尔表达式。实现了一个返回取反布尔值的operator!定义,其结果必须再次取反。请查看Safe bool idiom


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