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
未指明哪一个是先评估的。当计算第二个参数时,还允许对第一个参数进行部分计算。
根据标准,
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.
因为在同一个标量对象上有多个具有副作用的操作,而这些操作彼此之间没有排序,所以您处于未定义行为的领域,甚至
编译器bug的第一条规则:这可能不是编译器bug,而是您的误解。在同一语句中使用后缀和前缀运算符会导致未定义的行为。尝试使用
让我们看看GCC 4.2.1在询问有关
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)也没有实现++或--。