【问题标题】:A specific short-circuiting example in CC中的具体短路示例
【发布时间】:2021-02-25 19:46:59
【问题描述】:

我了解与操作符短路的基本概念,但为什么会这样做

int i = 0, j = -1, k = 1, m;
m = !(i++ && ++j) || ++k;
printf("%d %d %d %d", i, j, k, m);

有 1 -1 1 1 作为输出?具体来说,为什么 j == -1 而不是 0?

我知道已经有人问过类似的问题,但我不明白这个我在任何地方都找不到的具体示例。

【问题讨论】:

  • 为什么j 应该是0?
  • i++ 为假,因此&& 连词为假,++j 未计算。
  • 后增量 i++ 返回 i 的原始值(在增量之前),该值为零。所以&&之后的部分没有被评估(因为捷径)。
  • @dxiv: 你的意思是i 是假的,所以i && ... 没有被评估,以此类推。
  • @DavidIlic:能不能把它编译成ASM代码,让我们看看?

标签: c logical-operators short-circuiting logical-or logical-and


【解决方案1】:
i = -1;
i++;         // value of expression is -1
             // side effect is changing i to 0
if (i++) ;   // value of `i++` is zero; the if will not "trigger"

i = 0;
if (i++ && foo) ; // i++ has value of zero (false)
                  // so false && <anything> is false
                  // so foo is not evaluated

【讨论】:

  • 是的,我现在明白了。谢谢
  • 我不知道:为什么i 等于-1?
  • 我以-1 为例,这样我就不必两次0
【解决方案2】:

int i = 0, j = -1, k = 1, m;

!(i++ &amp;&amp; ++j) || ++k; ==> 只会评估i++,不会评估jk

假设我们正在替换变量的值,那么表达式如下所示。

!(0 &amp;&amp; ++ -1) || ++1

第 1 步: !(0 &amp;&amp; ++ -1) ==> 对于 &amp;&amp; 运算符,如果左侧操作数为 False,则我们不需要检查右侧操作数,因此 -1 不会递增,因此 j 的值将是 -1 本身。

因此|| 之前的左侧表达式变为!(0)

第 2 步: !(0) || ++1

现在 !(0) 将为 1 ,因此对于 || 运算符,如果左侧操作数为 TRUE ,则​​无需转到右侧操作数,则 ++k 将不会被执行。

m = 1 || ++1 ==> 1

因为只评估了i++,它会将其值更改为1 所以输出是:1 -1 1 1

【讨论】:

    【解决方案3】:

    后缀自增运算符的值是其操作数在自增前的值。

    所以表达式 i++ 的值等于 0,因为变量 i 被初始化为 0。

    既然子表达式i++ 的值为0,那么这个表达式中的子表达式++j

    (i++ && ++j)
    

    未计算,表达式本身的值为0

    应用否定运算符

    !(i++ && ++j)
    

    你会得到1(逻辑正确)。所以表达式的子表达式++k

    !(i++ && ++j) || ++k
    

    不会被评估。

    因此,整个表达式的值等于分配给变量m1

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

    另一方面,正如开头所指出的那样,表达式i++ 被求值。所以在这条语句之后i 将等于1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-26
      • 2012-05-28
      • 1970-01-01
      • 2011-05-29
      • 1970-01-01
      • 2010-11-21
      相关资源
      最近更新 更多