让e1
和e2
成为两个布尔表达式。然后,e1 && e2
相当于C中的e2 && e1
我的直觉告诉我是的。简单逻辑A & B
相当于B & A
。这在C中也是如此吗?
答案 0 :(得分:14)
逻辑上,是的。 1}}从逻辑角度看,e1 && e2
的结果永远不会与e2 && e1
不同。
但从代码角度来看,如果对e1
或e2
的评估有副作用,那么否,则它们并不完全等效。
具体来说,有时人们使用functions in a chain of &&
。
if( isHungry() && hasFood() ) eat() ;
通常你会想把最便宜的放到评估条件第一个,只检查第二个条件如果第一个条件保持为真。 短路评估是保证这种情况发生的原因。如果AND逻辑运算中的第一个条件为假,则甚至不评估第二个语句,因为最终结果不会为TRUE (FALSE && (TRUE && TRUE && TRUE && TRUE)) == FALSE)
。
换句话说,如果你甚至没有饥饿,你就不会费心去检查冰箱。
有时人们 依赖 关于短路评估将会发生的事实,并编写依赖于它的代码 。这类事情如下面的评论所示:
if( x && x->eval() ) { /* do something */ }
所以,上面说x=NULL
。会发生什么?尝试依赖空指针?应该写成
if( x )
{
if( x->eval() )
{
// do something
}
}
我说没有!短路评估意味着,如果x==0
,&&
中的if( x && x->eval() )
运算符的右操作数甚至不会被查看。不会评估x->eval()
,也不会发生空指针异常。
如果您在if语句中运行的函数具有副作用,则需要注意的另一件事是,例如递增某种类型的计数器。因此,如果 hasFood()具有内部计数器增量,例如fridgeCount++
。
即使是简短的cct评估,该函数也不会运行,所以当你点击if语句时,你期望发生的任何副作用都可能不会发生。
OR运算符也有短路评估,仅在if( e1 || e2 )
中,如果e1
变为TRUE,则语句被短路为TRUE(然后e2甚至不被评估,整个表达式为被视为TRUE
)。
这种行为适用于C / C ++,Java,JavaScript,PHP,Python和许多其他语言。
答案 1 :(得分:2)
是的,但评价不同。让我指出一个重要的例子。
e1 = (pStruct == NULL)
e2 = (pStruct->value != 0)
e1 && e2
是可以接受的,但如果e2 && e1
为pStruct
,则NULL
会导致段错误,因为&&
从左到右进行评估
答案 2 :(得分:0)
如果e1
和e2
是没有副作用的表达式且它们都是独立有效的,那么这是等效的。
在实践中,即使两个表达式都没有因短路行为而产生副作用,它们也可能无法产生相同的结果:
// given some array X of 10 members
if (i < 10 && x[i] < 5) {
//... this is not 'equivalent' to:
if (x[i] < 5 && i < 10) {
// ... but obviously:
if (i < 10 && z > 15) {
// ... is equivalent to:
if (z < 15 && i < 10) {
因此,对于任何布尔表达式e1
和e2
: no的一般情况,它们不等同。
对于特定情况:是的,它们在逻辑上可能是等价的。
答案 3 :(得分:0)
是和否。但是99%(实际上,可能更多,更多)的时间,是的。
如果您只谈论结果,那么是的。但是,如果你的表达式包含一个函数或赋值(或任何可以改变某些东西状态的东西),那么你应该知道C对如何评估&amp;&amp;的参数很聪明。
如果第一个表达式为&amp;&amp; (左值)为false,不会评估第二个表达式(正确的值)。
例如,可以安全地执行以下操作:
struct some_struct *x = NULL;
if (x && x->some_struct_value) {
// Some code here
}
由于左值x
被评估为false
,因此不会评估通常会导致应用程序崩溃的正确值x->value
,并且您的应用程序不会崩溃。< / p>
另一个例子是这样的:
int always_returns_false() {
return 0;
}
int increment(*int x) {
(*x)++;
return 1;
}
int main() {
int my_int = 0;
if (always_returns_false() && increment(&my_int)) {
// Stuff! (Or no stuff, doesn't matter!)
}
return my_int;
}
如果切换条件11中的表达式,则返回状态为0或1。
所以,从逻辑上讲,(e1 && e2) == (e2 && e1)
在功能上至少在C中会导致不同的行为和结果。
答案 4 :(得分:0)
e1 && e2
可能不等同于e2 && e1
,因此如果这些表达式有副作用,则会导致不同的行为。 6.5.13
逻辑AND运算符段 4 中的C99 draft standard说:
与按位二进制&amp;操作员,&amp;&amp;运营商保证从左到右的评估; 在评估第一个操作数后有一个序列点。 如果是第一个操作数 比较等于0,第二个操作数未评估。
因此,如果第一个操作数等于0
,则不会计算第二个操作数。所以,假设e1
评估为0
但e2
评估为非零值,那么在这种情况下:
e1 && e2
然后e1
将被评估,但e2
将不会,但在这种情况下:
e2 && e1
将评估e1
和e2
。