【问题标题】:operator precedence order and evaluation confusion [closed]运算符优先顺序和评估混淆[关闭]
【发布时间】:2013-07-15 12:02:58
【问题描述】:

在书籍和here 中,鉴于递增和递减运算符的优先级高于三元运算符,但为什么在下面的代码中,b 和 c 的值都没有递增但只有 b 递增(或 c 递增是条件为假)

int a=1,h;
h = (a==1)?++b:++c;
printf("%d%d",b,c);

甚至对于像

这样的语句
++i&&++j||++k;   // why not all the increment and decrement operator executes first

如果我犯了一些概念上的错误,请解释一下,抱歉我太菜鸟了 (如果这是重复的,请将我重定向到原始问题,我没有找到)

【问题讨论】:

  • 好吧,我希望这种混淆能对编写这样的代码起到强有力的威慑作用。
  • 哦,“太本地化了”,你去哪儿了? :(
  • @sumitb 你对三元运算符的作用有清楚的了解吗?
  • 两个字:懒惰的评价。
  • 如果此代码的作者为我工作,我将应用“粉红滑倒”威慑。

标签: c++ c operators operator-precedence


【解决方案1】:

条件 (?:)、逻辑合取 (&&) 和逻辑析取 (||) 运算符是惰性的。它们只评估产生结果所必需的操作数。

在条件运算符的情况下,它只计算两个分支之一;如果条件为真,则为第一个,如果条件为假,则为第二个。

如果左侧表达式的计算结果为假,则逻辑连接运算符不会计算右侧表达式,因为无论如何结果都会为假。逻辑析取运算符以类似的方式运行,不同之处在于如果左侧评估为真,它将不会评估右侧:true || x 始终为真,无论x


除非您正在处理重载的&&||。重载的运算符无法对操作数执行惰性求值。

【讨论】:

  • @ShafikYaghmour 永远不会发生。它从不评估这两个分支。
  • 啊。条件运算符不能重载,因此不适用。我会改写的。
  • +1 现在很清楚了。
【解决方案2】:

对于h = (a==1)?++b:++c;,请参阅C11 6.5.15 条件运算符 p4(我的重点

计算第一个操作数;它之间有一个序列点 评估和第二个或第三个操作数的评估 (以评估为准)。 第二个操作数只有在 首先比较不等于0;仅在以下情况下评估第三个操作数 第一个比较等于 0;

这证实了您观察到只有++b++c 之一被执行是正确的。

对于++i&&++j||++k;,请参阅 C11 部分 6.5.13、6.5.14。逻辑 OR 和 AND 运算符都从左到右求值,一旦知道结果,就跳过进一步的表达式求值(因此,一旦表达式求值为非零,||;一旦表达式求值为零,&&)。

【讨论】:

    【解决方案3】:

    三元运算符只计算条件操作数和恰好为真的操作数。您的案例中的 ++c 部分根本不会被评估。

    在第二种情况下,并非所有操作数都被计算,因为||&& 运算符执行所谓的“短路”,也就是说,如果整个表达式没有机会改变它的结果不再是,其余的操作数不会被计算。

    【讨论】:

      【解决方案4】:

      优先级不控制评估顺序。。它只控制运算符和操作数如何组合在一起。

      ||&& 运算符都强制从左到右求值,并且都是“短路”运算符;如果表达式的值可以从左边的表达式中确定,那么右边的表达式根本不会被计算。

      所以给定一个类似的表达式

      a++ || b++ && c++
      

      如果a++ 的结果不为零,那么无论b++ && c++ 的结果如何,结果都将为真,因此根本不计算右侧。

      【讨论】:

        猜你喜欢
        • 2016-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-14
        • 1970-01-01
        • 1970-01-01
        • 2018-03-28
        相关资源
        最近更新 更多