当代码包含多个NOT运算符时,我很困惑:
if (!x != !0)
;
或类似的。我可以把它读作:如果NOT x不等于NOT零, 但在我看来,我对它的实际含义完全感到困惑。
你对此有什么建议吗?即如何理解这些代码,从哪里开始阅读等等。
另一个例子:
if(!x == !1)
答案 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 ++中,true
为1
而false
为0
答案 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
类型,完全有两个值,bool
和true
(表示为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 list,question 9.2。
(哦,等等。一个更多的东西。&#34;富裕&#34;的反面不一定&#34;穷人&#34;当然。: - ))