0

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

# include <stdio.h>

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

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

  1. k>40应该检查这应该导致 0
  2. k==35应该检查,这应该导致 1
  3. 最后 50 应该被分配到k哪个应该输出 50

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

4

3 回答 3

6

您不能依赖此程序的输出,因为它是undefined behaviorC 中未指定评估顺序,因为这允许编译器更好地优化,来自标准部分段落C99草案:6.53

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

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

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

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

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

更新

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

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

但段落3说:

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

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

于 2013-08-14T12:28:50.027 回答
0

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

于 2013-08-14T12:28:03.500 回答
0

这是未定义的行为

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

于 2013-08-14T12:29:03.520 回答