NOT运算符有什么作用?

6

目前正在使用这个教程学习C++。它解释了! NOT操作符是什么,但我不确定为什么会想要使用它。能否有人解释一下?


5
如果没有使用 if(!x),你将如何表达这个意思,我很感兴趣。 - PlasmaHH
6
如果(static_cast<bool>(x) == false),显然。 - user784668
3
显然,时髦的做法是:如果(x),则什么也不做,否则就做某事。 - Green Demon
12个回答

13
< p > 运算符在您想要检查某个条件当前未被满足时非常有用。

想象一个告诉您特定子系统是否已初始化的函数和另一个用于初始化它的函数:

bool subsystem_is_initialized();
void subsystem_initialize();

您可以检查它是否已初始化,并使用not运算符进行初始化(如果尚未初始化)。

if (!subsystem_is_initialized())
    subsystem_initialize();

就实际目的而言,它是一种将值与零进行比较的更短的方式,并明确建议受影响的值是布尔值。您不一定需要它,但是同样,您也不需要乘法(可以使用加法循环),加法(可以使用二进制逻辑进行运算)或大多数二进制逻辑(我听说可以使用NANDs做任何事情,但我自己没有研究过)。

还要记住,像几乎所有其他 C++ 运算符一样,它可以被类重载。


更不用说它比明确地与0进行比较更易读了。 - svidgen
你也可以使用“双重否定”将某些内容转换为布尔值。在动态类型语言中,经常看到模式 !!,它首先将值转换为 truefalse,然后再取反。但在 C++ 中这种方式不太常见,因为 return foo 会自动转换为适当的返回类型。 - tadman

5
一门语言通常不是(事实上几乎从来不是)定义为具有最小功能集,而是定义为具有有用的功能集。例如,如果您有以下代码:
if (!test_something())
  do_something();

你也可以这样表达:
if (test_something()) {
} else
  do_something();

但这样会使阅读变得更加困难。因此,虽然C++语言通常可以用其他结构来表达逻辑否定,但为了表明您的意图,显式地表达否定有助于提高可读性。


一个空的 if 子句很凌乱,应该避免使用。看起来你本来想在那里放置一些内容,但却忘记了。 - tadman
@tadman:这基本上就是我的观点。它是合法的,但很丑陋,所以你最好使用 ! - bitmask

5

当您需要在条件中翻转真/假以增加可读性时,可以使用它。 例如: 比较

// Ensure that the thing is NOT red.
if (thing_is_red() == false)
    ...
if (!thing_is_red())
    ...

这也比严格断言与NULL相比要好得多,例如if (pointer != NULL)if (pointer)if (pointer == NULL)作为if (!pointer) - tadman
@tadman 这将取决于所使用的编码风格。就我个人而言,我只在比较真或假时使用 ! 来翻转条件。我发现用 NULL 或其他数据值替换明确的比较需要太多对你所使用的语言的特定问题的了解。真/假存在于计算机之外,在传统逻辑中,这是所有程序员都需要掌握的东西,不管所使用的编程语言如何。 - E.T.
如果你不了解C++的“特殊习惯”,那么你可能不应该使用C++进行编程,就像不知道如何正确使用链锯意味着你不应该使用链锯一样。宽容并不是一个用来描述C++的术语。 - tadman

2

!操作符用于bool条件检查中的否定目的。你可以在许多地方使用它。简单的例子:

 if (!existInArray(A, i))

检查数组中是否不存在i


2

! 或 NOT 运算符是逻辑上的 NOT 门。

因此,NOT 门真值表表示如果 x 是 true,那么 !x 就是 false,反之亦然。

如果你从逻辑角度考虑,这并不太困难。例如,男性的 NOT 是女性,true 的 NOT 是 false,简单的 NOT 是复杂的。


这些都是相当糟糕的例子。性别很少是二元的事情。 - tadman
@tadman,甚至跨性别者也喜欢将自己分类到其中之一。这只是一个例子 :-) - Aniket Inge
“NOT”并不意味着相反。 - Pubby
1
@Pubby 我不确定我在布尔代数中理解了那个 :-) - Aniket Inge
我的意思是模拟世界很少是绝对的,在0.0到1.0的范围内,你很少会得到极端情况。而二进制世界则总是绝对的。性别是通常是男或女,但也经常是其他东西,比如雌雄同体或故意不明确。 - tadman
@tadman 我同意,现实世界是模糊的。我一直在思考这个问题 - 这就是为什么模糊逻辑被认为是人工智能,因为它试图尽可能准确或不准确地模拟现实世界。 - Aniket Inge

2
你提到的 教程
引用: “NOT”运算符只接受一个输入。如果该输入为TRUE,则返回FALSE,如果该输入为FALSE,则返回TRUE。
这意味着“NOT”运算符是一元运算符,即单个操作数(不是二元运算符)。
例如:&& 和|| 是二元运算符,它们的语法如下:
  result = operand1  && operand2
  result = operand1  || operand2

Unary is:

  result = !operand1 

其结果值是操作数值的反转,如果 operand1 = True,则结果为 False;如果 operand1 = False,则结果为 True。
同样的内容在这里写道:

例如,NOT (1) 的计算结果为 0,而 NOT (0) 的计算结果为 1。NOT(任何非零数)的计算结果为 0。在 C 和 C++ 中,NOT 写作 !。NOT 在 AND 和 OR 之前计算。

在 C/C++ 中,0 表示 False,非 0 表示 True。
还有一些好的例子!
!( 1 || 0 )  

我们知道 1 || 01,表示为真,而应用 NOT 运算符后变成 0,表示为假:
    !( 1 || 0 )  
=>  ! (1)     
=>  0  that is false

你注意到在这个表达式中我们有两个运算符,逻辑或 || 和非 ! 运算符。
    !( 1  || 0 )  
    ^      ^
    NOT   OR  

"并且请注意 OR 运算符中的两个操作数,对于一元 NOT 只有一个操作数。"

你所参考的教程很不错。 - Grijesh Chauhan

2
最常见的情况可能是使用 std::istream
int i;
std::cin >> i;
if ( ! std::cin ) {
    //  Something went wrong...
}

除此之外,各种类都有isValid()isDone()函数;例如,使用GoF迭代器进行迭代:

for ( IteratorType i( init ); ! i.isDone(); i.next() ) {
    //  Do something with i.element()
}

地图类通常有一个contains函数,因此您可能会问

if ( ! myMap.contains( key ) )

有时,您还需要使用布尔变量:例如,在需要进行一些复杂的评估的匹配条件的线性搜索中:

bool found = false;
int current = 0;
while ( ! found && current != end ) {
    //  maybe set found...
}

2

好的,如果你想将两个数字的和除以第三个数字,那么只有当第三个数字不为零时才能这样做。

    #include <iostream>
    using namespace std;
    int main()
   {
    int a,b,c,sum;
    cin >> a >> b >> c;
    sum = a+b;
    if (c!=0) //which is equivalent to if(!c)
    cout << sum/c;
   }

我使用了一个简单的例子,以便快速理解。现在一切都好了吗?祝你学习顺利。


2
我认为这不是一个很好的例子。!=当然不同于!,使用!作为与零比较的速记方式并不理想。 - Pubby
1
我知道,但他刚开始学习C++,我只是想给他一个关于这种类型的运算符的提示。当他成为“大人物”时,他会明白我是个愚蠢的新手,我的回答很烂。现在,简短而简单的回答就足够了。 - George Netu

1
!操作符的作用是将一个表达式从false转换为true。它通常用作== false== 0的替代品。它经常使表达式更易于阅读:
如果(p == NULL || p->next != NULL)
相当于:
如果(!p || p->next)
[好吧,这里的“更易于阅读”显然是非常主观的]。

你的检查有误。如果你想避免在 p->next 上进行非法访问,应该是 p != NULL - zneak
不,我搞错了 && 和 || 的使用... ;) - Mats Petersson

1
您有很多答案解释NOT运算符。
我个人不太喜欢! 运算符。它没有应有的可见性(即,它颠倒了从句的含义)。
例如,尽管我在C++中编程已经几年了,但我仍需要几秒钟来解析if ( ! ptr ),而if ( ptr == NULL )立即传达了它的含义。
if ( ! (i % 2) ) 检查偶数还是奇数?如果你在看到问号后没有答案,或者需要再次查看if条件,那么你刚刚证明了我的观点。
回顾帖子,我同意一些帖子的作者认为NOT运算符在应用于bool和函数调用时具有有效的用途。在处理流时使用!被认为是惯用语。

话虽如此,我认识的几乎每个程序员都曾被strcmp咬伤过。我曾在一家商店工作,那里有一些#define,例如#define STRCMP_EQUAL 0等,并要求将检查写成if ( STRCMP_EQUAL == strcmp(str1, str2) ),在我看来,这比if ( ! strcmp(str1, str2) )明显得多。


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