【问题标题】:Why isn't "k" incremented in the statement "m = ++i && ++j || ++k" when "++i&&++j" evaluates to true? [duplicate]为什么当 "++i&&++j" 计算结果为真时,"k" 在语句 "m = ++i && ++j || ++k" 中不递增? [复制]
【发布时间】:2013-04-22 17:08:01
【问题描述】:

复合逻辑AND/OR表达式中的各个表达式是否应该在将逻辑运算符应用于其结果之前先进行评估?为什么++k在条件@987654322中保持不变@ 用于以下程序:

 #include<stdio.h>

 int main()
 {
      int i=-3, j=2, k=0, m;
    m = ++i && ++j || ++k;
    printf("%d, %d, %d, %d\n", i, j, k, m);
    return 0;
}

输出: -2,3,0,1

但我希望输出-2,3,1,1

【问题讨论】:

  • 因为标准保证了短路。由于++i &amp;&amp; ++j 评估为true,因此无论|| 的评估如何,最终结果都将评估为true,因此最终的|| 根本不会被评估。这被称为短路。 C 和 C++ 标准保证 || 和 &amp;&amp; 运算符的这种行为。
  • 我确实回答了,但我不明白为什么人们在深入研究他们的 C 编程语言书之前先在 StackOverflow 上提问。
  • “复合逻辑 AND/OR 表达式中的各个表达式不应该首先被求值吗”——不,当然不是,即使是最基本的 C 语言阅读也能说明这一点你。
  • @ruppell's Yes 当然,您只需将逻辑 OR 运算符替换为按位 OR 运算符即可获得输出。

标签: c expression logical-operators


【解决方案1】:

逻辑运算符具有短路求值,即,一旦为表达式确定了一个值,就不会对表达式的其余部分进行求值。

例如m = ++i &amp;&amp; ++j || ++k; 在这个 ++i -> true, ++j -> true (非零值) 因此m = true &amp;&amp; true || ++k;

现在为真 && 真为真 所以

m = true || ++k 

与 OR 运算符一样,如果一侧为真,则另一侧不求值,因此结果为真。

因此 k 不递增。

【讨论】:

    【解决方案2】:

    您应该避免编写此类不可读的代码。它实际上被解析为

    m = (++i && ++j) || ++k;
    

    所以一旦j &gt;= 0 ++j 条件总是为真,所以++k 不会被评估,因为&amp;&amp; 是一个捷径然后但是|| 是一个捷径切割否则(因此他们可能不会评估他们的正确操作数)。

    所以&amp;&amp; 的求值如下:左操作数被求值,如果为假则返回,然后只有当它为真时(即不等于0)右操作数被求值并返回为&amp;&amp; 的评估结果。同样|| 的评估如下:左操作数被评估。如果它为真(非零),它将成为|| 的结果;否则,正确的操作数被计算并且是|| 表达式的结果。

    特别是,在编码if (x &gt; 0 &amp;&amp; 20/x &lt; 5) 时,从未尝试对x==0 进行除法。

    另请阅读维基百科operators in C & C++ & short circuit evaluation & lazy evaluation 页面;请花几个小时阅读一本好的 C 编程书籍。

    【讨论】:

    • 请详细说明“然后”和“否则”部分。
    • 谢谢。但我猜"then only when it is true (i.e. not equal to 0) the right operator"这行有错字。应该是right operand
    • 谢谢。错字已更正
    【解决方案3】:

    m = ++i && ++j || ++k;

    上面的代码行首先执行 ++i 和 ++j 并且不执行 ++k 因为它写在 || 之后(或)

    在 || 的情况下,当先前的语句已经为真时,逻辑电路运算符不执行在 && 的情况下为 false

    因此 k 未被触及

    【讨论】:

      【解决方案4】:

      &amp;&amp; 和 || 是逻辑运算符,您在上下文之外使用它们,这很奇怪(对于 C/C++ 可以,但在 Java 或 C# 中会出现类型错误)。

      您刚刚发现了短路运算符 - 如果您“知道”它是真的,则不需要评估整个表达式。即 i 和 j 不为零,因此您无需对 k 做任何事情,因为您知道表达式为真。

      【讨论】:

        【解决方案5】:

        这是逻辑运算符的快捷方式,在您的情况下为运算符||。当第一个操作数为true 时,第二个操作数不可能对结果产生任何影响。无论第二个操作数产生什么,它总是正确的。所以第二个操作数不会被计算。

        如果发现第一个操作数是false,则逻辑&amp;&amp; 运算符也是如此。第二个操作数无关紧要,结果将始终为false,因此不会计算第二个操作数。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-02-15
          • 1970-01-01
          • 2018-09-06
          • 2021-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多