在使用多个逻辑NOT运算符评估条件时出现混淆

时间:2018-05-08 07:30:05

标签: c++ c

当代码包含多个NOT运算符时,我很困惑:

if (!x != !0)
  ;

或类似的。我可以把它读作:如果NOT x不等于NOT零, 但在我看来,我对它的实际含义完全感到困惑。

你对此有什么建议吗?即如何理解这些代码,从哪里开始阅读等等。

另一个例子:

if(!x == !1)

7 个答案:

答案 0 :(得分:6)

如果您不确定,可以使用truth table。例如

x | 0 | x!=0 | !x | !0 | !x != !0
0 | 0 |  0   |  1 |  1 |    0
1 | 0 |  1   |  0 |  1 |    1

如果有许多&&和和||,使用de Morgan's laws

答案 1 :(得分:1)

为了简单起见,首先评估operator!,然后阅读L-> R.

要记住的事情:

!0 = 1 // true
!1 = 0 // false

所以你的病情可以简化为:

if (!x != true)  // !0
if (!x == false) // !1

现在,反转时的任何非零值都为zero

int x = 10;
!x // zero
反转时

true

int x = 0;
!x // one

在C或C ++中,true1false0

答案 2 :(得分:0)

我认为问题是关于C的,因此我将在C中给出答案。

您需要知道优先级规则 - !!=更强大。因此,可以使用括号(!x) != (!0)来澄清表达式。现在,接下来要知道!将会做什么 - 如果操作数非零,则结果为0,如果为零则为1 。因此,!0可以恒定折叠为1

现在我们有(!x) != 1。由于!x为1 iff x为零,因此如果x为非零,则整个表达式的结果为1,否则为0。

因此,我们可以将这种表达式简化为更惯用的双重否定:!!x。但是,if子句本身测试表达式是否为非零,因此整个if语句可以更改为if (x) ;(并且因为表达式仅保护空语句,它可以完全省略)

答案 3 :(得分:0)

当我开始在PowerBuilder上开发时,我对simalar语法也感到困扰,然后我意识到我只需要将它想象为嵌套,如果检查错误。 例如!x变为if(x)= false,因此当x为假或零时,它更清楚为真。 在C 0是假的,任何不为零都是真的。

在同样的逻辑中!1总是假的!0总是如此,尽管我看不出以这种令人困惑的方式输入它的原因,也许你正在看的代码来自某种自动生成器/转换器。

答案 4 :(得分:0)

首先看看operator precedence。您会看到! !=优先于logical operators!0

其次,int是什么 - 这可疑听起来像是从bool!0的隐式转换 - 否则!x根本就没有意义。< / p>

在您的示例中,您需要首先评估逻辑运算符(即!0!=),然后检查它们是否不等于<?php use Doctrine\DBAL\Driver\PDOMySql\Driver as PDOMySqlDriver; $connPdo = null; try { $connPdo = new PDO("odbc:DRIVER={Devart ODBC Driver for ASE};host=Develop;dbname=poc;charset=utf8", "sa", ""); $connPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { echo $e->getMessage() . '</br>'; } return [ 'doctrine' => [ 'connection' => [ 'orm_default' => [ 'driverClass' => PDOMySqlDriver::class, 'params' => [ 'pdo' => $connPdo ] ], ], ], ]; 。也就是说,这种代码非常糟糕因为真的很难阅读 - 如果可能的话,避免编写这样的代码(并考虑重构它 - 同时由单位覆盖)测试 - 如果你在“野外”中遇到它)

答案 5 :(得分:0)

这种代码旨在欺骗您。你的大脑难以处理双重否定或三重否定(而你不是唯一的否定)。

您需要知道优先级规则是什么,并应用它:

(!x == !1)等于((!x) == (!1))

如果您在代码审核期间看到此类代码,则应明确突出显示该代码,并要求更新。

请注意,在C ++中,您还可以使用not代替!。它可以使事情更容易理解:

(!x == !1)等于((not x) == (not 1))

答案 6 :(得分:0)

在C和C ++中,值为零&#34; false&#34;,并且非零值被视为&#34; true&#34;。但它偶尔会引起混淆,偶尔也会引起一些小问题,即使两种不同的价值不同,也可以认为是真实的。

例如,假设你有一个函数is_rich()告诉你一个人是否富裕。假设您编写了这样的代码:

int harry_is_rich = is_rich("Harry");
int sally_is_rich = is_rich("Sally");

现在变量harry_is_rich根据Harry是穷人还是富人而为零或非零,根据Sally是贫穷还是富有,sally_is_rich为零或非零。

现在假设您有兴趣了解Harry和Sally是否富有,或者两者都是穷人。你的第一个想法可能是

if(harry_is_rich == sally_is_rich)

但是等等。由于任何非零值都被认为是&#34; true&#34;在C中,如果出于某种原因,当哈利富裕时is_rich()函数返回2,并且当莎莉富有时返回3,该怎么办?这不会是一个错误,本身 - is_rich()函数完全符合其规定的返回非零值,如果这个人有钱 - 但它会导致你的情况不能写

if(harry_is_rich == sally_is_rich)

(当然,你可以编写它,但是像任何错误的代码一样,它可能无法正常工作。)

那你可以做什么呢?好吧,一种可能性就是写

if(!harry_is_rich == !sally_is_rich)

你可以将其视为&#34;如果不是哈利富裕的情况与萨莉富裕的情况具有相同的真实价值&#34;。而且,虽然它显然有点扭曲,但你可以说服自己,它意味着&#34;同样的事情。

而且,虽然它有点令人困惑,但它具有工作的优势。它的工作原理是因为C和C ++中的真/假值的另一个令人困惑的方面。

虽然如我所说,零被认为是假的,任何非零值都被认为是真的,生成真/假值的内置运算符 - 像&&||! - 实际上保证会给你正好0或1.(也就是说,内置函数在这方面与is_rich()等函数有很大不同。通常,{{1}可能会为&#34; true&#34;返回2,或3或37.但is_rich()&&||保证为true返回1,为0假的。)

所以,当你说!时,如果哈利富有,你就会得0,如果哈利不富裕,你就得1。当你说!harry_is_rich时,如果莎莉有钱,你将获得0,如果莎莉不富有,你将获得1。如果你说

!sally_is_rich
无论if(!harry_is_rich == !sally_is_rich) 选择返回什么值,你都能正确发现哈利和莎莉是富人还是贫穷人。

还有一件事。在所有这些中,我一直在考虑整数(或其他可能有很多值的类型)。但是C和C ++都有is_rich()类型,更简洁地表示真/假值。对于bool类型,完全有两个值,booltrue(表示为1和0)。因此,对于false类型,您不能拥有除1以外的任何值的真值。因此,如果bool函数被声明为返回is_rich(),或者如果你将变量声明为bool,那么这将是强制值为0/1的另一种方式,在这种情况下是条件

bool

会正常工作。 (此外,当我说像if(harry_is_rich == sally_is_rich) &&||这样的运营商保证正好返回1或0时,这主要是因为这些运营商不会这样做&#34;返回&#34;任意整数,但改为&#34;返回&#34; bools。)

另请参阅C FAQ listquestion 9.2

(哦,等等。一个更多的东西。&#34;富裕&#34;的反面不一定&#34;穷人&#34;当然。: - ))