关于c ++:意外的评估顺序(编译器错误?)

Unexpected order of evaluation (compiler bug?)

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Undefined Behavior and Sequence Points

我不确定这是否是GCC错误,所以我会问:

1
2
unsigned int n = 0;
std::cout << n++ << n << ++n;

GCC给出了非常奇怪的结果:"122",这是不可能的。因为<<是左相关的,所以它应该与以下内容相同:

1
operator<<(operator<<(operator<<(std::cout, n++), n), ++n)

因为在评估参数之前和之后都有一个序列点,所以N在两个序列点之间永远不会被修改两次(甚至是被访问),所以它不应该是未定义的行为,只是评估顺序未指定。

因此,有效的结果将是:一百一十一012002一百零一

没有别的了


在计算参数和调用函数之间有一个序列点。在评估不同参数之间没有序列点。

让我们看看最外层的函数调用:

1
operator<<(operator<<(operator<<(std::cout, n++), n), ++n)

这些论点是

  • operator<<(operator<<(std::cout, n++), n)

  • ++n

未指明哪一个是先评估的。当计算第二个参数时,还允许对第一个参数进行部分计算。

根据标准,[intro.execution]节(3225号草案的措辞):

  • If A is not sequenced before
    B and B is not sequenced before A, then A and B are unsequenced. [ Note: The execution of unsequenced
    evaluations can overlap. — end note ]

  • Except where noted, evaluations of operands of individual operators and of subexpressions of individual
    expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution
    of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be
    performed consistently in di?erent evaluations. — end note ] The value computations of the operands of an
    operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar
    object is unsequenced relative to either another side effect on the same scalar object or a value computation
    using the value of the same scalar object, the behavior is unde?ned.

因为在同一个标量对象上有多个具有副作用的操作,而这些操作彼此之间没有排序,所以您处于未定义行为的领域,甚至999都是允许的输出。


编译器bug的第一条规则:这可能不是编译器bug,而是您的误解。在同一语句中使用后缀和前缀运算符会导致未定义的行为。尝试使用-Wall选项来提供更多的警告,并向您展示代码中的潜在缺陷。

让我们看看GCC 4.2.1在询问有关test.cpp的警告时告诉我们什么:

1
2
3
4
5
6
7
#include <iostream>

int main() {
    unsigned int n = 0;
    std::cout << n++ << n << ++n << std::endl;
    return 0;
}

当我们编译时:

1
2
3
$ g++ -Wall test.cpp -o test
test.cpp: In function ‘int main():
test.cpp:5: warning: operation on ‘n’ may be undefined


您的代码就是一些书中的一个例子,说明了为什么经验丰富的程序员不喜欢(++,--)运算符重载,甚至其他语言(Ruby)也没有实现++或--。