【问题标题】:C Programming : Confusion between operator precedenceC编程:运算符优先级之间的混淆
【发布时间】:2013-08-16 09:42:39
【问题描述】:

我对运算符的优先级感到困惑,想知道如何评估此语句。

# include <stdio.h>

int main()
{
  int k=35;  
  printf("%d %d %d",k==35,k=50,k>40);  
  return 0;  
}

这里k 最初的值为35,当我在printf 中测试k 时,我认为:

  1. k&gt;40 应该被选中,结果应该是 0
  2. k==35 应该被选中,结果应该是 1
  3. 最后 50 应该分配给 k 并且应该输出 50

所以最终输出应该是1 50 0,但输出是0 50 1

【问题讨论】:

  • 这是undefined行为的一个例子
  • 运算符优先级在这里无关紧要。
  • 在 gcc 版本 4.4.3 上它是 0 50 0 因为它是未定义的行为:(
  • 运算符优先级控制运算符的分组方式,但不控制它们的执行顺序 - 它控制评估什么,但不控制何时
  • @H2CO3 虽然未指定函数参数的求值顺序,但我相信这种特定情况也是未定义的行为,因为k 在 seq.点用于确定要存储的值以外的其他目的。 C99 6.5/2:Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.

标签: c operators operator-precedence


【解决方案1】:

你不能依赖这个程序的输出,因为它是undefined behavior,C 中没有指定评估顺序,因为这允许编译器更好地优化,来自C99 标准草案6.5 段落@ 987654326@:

运算符和操作数的分组由语法指示。74) 除非另有说明 稍后(对于函数调用 ()、&&、||、?: 和逗号运算符),子表达式的求值顺序和副作用发生的顺序都未指定。

它也是未定义的,因为您正在访问k 的值并在同一个sequence point 中分配给它。来自草案标准部分6.5 段落2

在上一个和下一个序列点之间,一个对象应该有它的存储值 通过表达式的评估最多修改一次。 此外,先验值 应为只读以确定要存储的值。

它引用了以下未定义的代码示例:

i = ++i + 1;
a[i++] = i; 

更新

关于函数调用中的逗号是否充当序列点有评论。如果我们看6.5.17 Comma operator2说:

逗号运算符的左操作数被评估为 void 表达式; 有一个 评估后的序列点。

3 段说:

示例如语法所示,逗号运算符(如本小节所述)不能出现在使用逗号分隔列表中的项目的上下文中(例如函数的参数或初始值设定项列表强>)。

所以在这种情况下,逗号不会引入序列点。

【讨论】:

    【解决方案2】:

    未指定计算函数参数的顺序。它们可以按任何顺序进行评估。编译器决定。

    【讨论】:

      【解决方案3】:

      这是undefined behaviour

      您可以获得任何价值。连续两次执行中缺少sequence points。增加警告的严格级别,你会得到warning: operation on ‘k’ may be undefined

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-26
        • 2013-02-24
        相关资源
        最近更新 更多