【问题标题】:operator precedence problem? [duplicate]运算符优先级问题? [复制]
【发布时间】:2011-08-31 17:47:32
【问题描述】:

可能重复:
Compilers and argument order of evaluation in C++

我有如下打印语句...

  int i=0;
  printf("%d,%d,%d,%d,%d,%d",i++,i,++i,i--,++i,i);

根据优先级i++,i,++i,i--,++i,i 应该像下面那样逐步评估...

0,i,++i,i--,++i,i   // after this i=1;

0,i,++i,1,++i,i    //  after this i=0;

0,i,++i,1,1,i      //  after this i=1;

0,i,2,1,1,i       //   after this i=2;

0,2,2,1,1,2       //   after this i=2;  

我认为这个逻辑的最终结果应该是......

 0,2,2,1,1,2 

但我收到2,2,2,1,2,2 这背后的原因是什么?

顺便说一句,我正在使用 Visual c++ 2010...

【问题讨论】:

  • 您观察到的行为与运算符优先级绝对无关。此外,运算符优先级并不决定“逐步”的评估顺序。你从哪里得到这个奇怪的想法?
  • 我的 turbo c 编译器得到了 1,1,1,1,1,0主要在编译器上1
  • @AndreyT 如果它不是编译器执行它的步骤过程
  • @niko 我知道它在 turbo c 评估中是如何工作的,一次从右到左一个变量;但在 vs2010 上,这不是理性的答案,因为我没有看到任何逻辑!
  • @teacher:没有人知道它是如何执行的。在 C/C++ 语言中,“步骤”的概念由所谓的 序列点 定义。序列点之间发生的一切都是一个不可分割的步骤。它无法分解为更小的步骤,因此无法进行有意义的进一步分析。

标签: c visual-c++


【解决方案1】:

这是未定义的行为。 C 和 C++ 语言标准明确未指定函数参数的评估顺序,以便让编译器在各种硬件上生成最佳机器代码。

您不能在序列点之间多次修改变量。语言标准规定序列点仅出现在代码中的特定点,例如分隔语句的分号。在初始赋值int i=0; 之后有一个序列点,在printf 返回之后有一个序列点,在printf 的所有参数都被计算之后但在printf 实际被调用之前有一个序列点,但在每个参数的评估之间没有一个序列点。

【讨论】:

  • 更重要的是,它是关于何时执行递增/递减运算符的实现决策。实施可以自行决定:
【解决方案2】:

不是。

这里的逗号操作符:

a,b;

以及分隔函数参数的逗号:

f(a,b);

不同。

只有真正的逗号运算符将是一个序列点,并将对左右参数进行排序(在我的示例中为ab 表达式)。

并且函数参数之间的逗号不是序列点,并且参数评估的顺序是未定义的(即使相同的编译器可能在不同的调用站点以不同的顺序评估它们)。此外,在序列点之间的程序部分中两次或更多次更改相同的左值(在您的示例中为i 变量)是非法的(未定义的行为)。同一对象的每次修改都必须通过序列点(例如使用;)与同一对象的另一修改分开。

【讨论】:

    【解决方案3】:

    在您的情况下,逗号不是保证按顺序计算的, 运算符,而是属于函数调用语法,并且计算函数参数的顺序是未定义的。因此,您的代码肯定会表现出未定义的行为(看起来确实如此)。

    【讨论】:

    • 正确,这些不是逗号运算符。
    【解决方案4】:

    由编译器生成什么代码。未定义函数调用的参数的评估顺序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-07
      • 2016-12-28
      • 1970-01-01
      相关资源
      最近更新 更多