【问题标题】:Short-circuit evaluation evaluating if( (a = 4) || (b = 6) || (c = 7) || (d = 8) )短路评估评估 if( (a = 4) || (b = 6) || (c = 7) || (d = 8) )
【发布时间】:2017-06-07 21:22:04
【问题描述】:

程序贴在下面:

#include <stdio.h>

int main(void)
{
    int a, b, c, d;

    printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);

    if( (a = 4) || (b = 6) || (c = 7) || (d = 8) )
        printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
}

我理解第一个 printf 语句,但在第二个 if 语句中,我不明白当只有一个等号而不是两个等号时它会评估什么。

输出是:

        a = 0, b = 0, c = 32767, d = -341260496
        a = 4, b = 0, c = 32767, d = -341260496

所以第二个 if 语句最终是真的,但是如何呢?
我认为一个等号会为变量赋值。

【问题讨论】:

  • 第一个 printf 是未定义的行为,因为你还没有初始化任何变量。
  • 没有初始化任何变量。最后,只有a 被设置为4,而其他的仍然未初始化。
  • 使用== 来测试是否相等。 a = 4 将值 4 分配给 a
  • 一个等号赋值,然后返回赋值(所以第一个赋值是true,其余的被跳过)
  • 只有a 被分配,因为它是短路。查看第一个 || 之后的任何内容是没有意义的,因此其他任务不会被执行。

标签: c if-statement logical-operators


【解决方案1】:

当只有一个等号而不是两个等号时,我不明白 if 会如何计算。

一个等号使它成为一个赋值。因此,a=4 的计算结果为4,它被逻辑“OR”运算符|| 解释为“真”。由于短路,此时不会发生进一步的评估,因此其余变量保留它们在 if 语句之前的值。

注意:打印未分配的变量会导致未定义的行为。您应该如下更改声明行:

int a = 0, b = 0, c = 0, d = 0;

【讨论】:

    【解决方案2】:

    这个 printf 调用

        int a, b, c, d;
    
        printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
    

    具有未定义的行为,因为变量 a、b、c 和 d 未初始化并且具有可能是陷阱值的不确定值。

    在if语句的条件下

    if( (a = 4) || (b = 6) || (c = 7) || (d = 8) )
    

    有赋值表达式

    a = 4
    

    根据 C 标准(6.5.16 赋值运算符)

    3 赋值运算符将值存储在由指定的对象中 左操作数。 赋值表达式具有左边的值 赋值后的操作数,111) 但不是左值...

    更进一步(6.5.14 逻辑或运算符)

    3 ||如果任一操作数比较,则运算符应产生 1 不等于0;否则,它产生 0。结果具有 int 类型。 4 不同于按位 |运算符,||运营商保证 从左到右的评估;如果计算第二个操作数,则有 第一个和第二个评估之间的序列点 操作数。 如果第一个操作数比较不等于 0,则第二个 不计算操作数。

    因此只有赋值

    a = 4
    

    将在这个if语句中执行

    if( (a = 4) || (b = 6) || (c = 7) || (d = 8) )
    

    所有其他变量仍将未初始化。

    由于赋值为 4 的值不等于 0,则执行 if 子语句。

    【讨论】:

      【解决方案3】:

      那么第二个 if 语句最终是真的,但是如何呢?

      在 C 中,赋值也是一种求值的表达式。该值(在大多数情况下)位于赋值的右侧。

      在这种情况下,(a = 4) 的计算结果为 4,即 C 世界中的 true,因此将整个条件短路并跳过对 bcd 的分配。这就是为什么只有 a 被初始化,而其他的则保留它们的垃圾值。

      【讨论】:

      • "值总是在赋值的右边。"嗯。不完全的。试试int i; float f = (i = 1.23); printf("%f\n", f);(i = 1.23) 计算结果为 (int) 1
      • @chux 哇,这很好。
      【解决方案4】:

      简而言之,当您使用 OR 进行比较时,会进行评估,直到第一次出现 TRUE。所以只分配了 a=4 。其余部分仍未初始化。

      【讨论】:

        猜你喜欢
        • 2012-02-10
        • 2012-12-16
        • 1970-01-01
        • 2019-12-28
        • 1970-01-01
        • 2021-11-21
        • 2017-09-10
        • 2015-11-14
        相关资源
        最近更新 更多