是e1&& e2相当于e2&& E1?

时间:2013-09-12 19:20:06

标签: c

e1e2成为两个布尔表达式。然后,e1 && e2相当于C中的e2 && e1

我的直觉告诉我是的。简单逻辑A & B相当于B & A。这在C中也是如此吗?

5 个答案:

答案 0 :(得分:14)

逻辑上,是的。 e1 && e2的结果永远不会与e2 && e1不同。

但从代码角度来看,如果对e1e2的评估有副作用,那么,则它们并不完全等效。

具体来说,有时人们使用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 && e1pStruct,则NULL会导致段错误,因为&&从左到右进行评估

答案 2 :(得分:0)

如果e1e2是没有副作用的表达式且它们都是独立有效的,那么这是等效的。

在实践中,即使两个表达式都没有因短路行为而产生副作用,它们也可能无法产生相同的结果:

// 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) {

因此,对于任何布尔表达式e1e2 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)

由于short circuit evaluation

e1 && e2可能不等同于e2 && e1,因此如果这些表达式有副作用,则会导致不同的行为。 6.5.13 逻辑AND运算符 4 中的C99 draft standard说:

  

与按位二进制&amp;操作员,&amp;&amp;运营商保证从左到右的评估;   在评估第一个操作数后有一个序列点。 如果是第一个操作数   比较等于0,第二个操作数未评估

因此,如果第一个操作数等于0,则不会计算第二个操作数。所以,假设e1评估为0e2评估为非零值,那么在这种情况下:

e1 && e2

然后e1将被评估,但e2将不会,但在这种情况下:

e2 && e1

将评估e1e2