意外的评估顺序(编译器错误?) [英] Unexpected order of evaluation (compiler bug?)

查看:208
本文介绍了意外的评估顺序(编译器错误?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

未定义的行为和序列点


如果这是一个gcc bug或者不是,所以我会问:

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

gcc给出了非常奇怪的结果:
122,AFAICT是不可能的。因为<<是左关联的,应该是相同的:

 运算符<<<(运算符< std :: cout,n ++),n),++ n)

点在评估参数之前和之后,n不会在两个序列点之间修改两次(甚至访问) - 因此它不应该是未定义的行为,只是未指定的评估顺序。



所以AFAICT有效的结果是:
111
012
002
101



/ p>

解决方案

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



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

 运算符<<<(运算符<<<<<<(std :: cout,n ++),n),++ n)
pre>

参数为




  • 运算符< ;(operator<



p>


  • ++ n



它未指定哪些首先被评估。



从标准中, [intro.execution] (来自草案3225的字词):



  • / em>之前未对
    B B 进行排序之前,和 B 未排序。 [注意:执行无序的
    评估可能会重叠。 - ]

    除非另有说明,个别运算子的操作数和个别
    表达式的子表达式的计算无序。 [注意:在程序执行$ ​​b $ b期间多次评估的表达式中,对其子表达式的无序和不确定顺序评估不需要在不同的评估中一致执行
    。 - end note ]
    运算符的操作数的值计算在运算符结果的值计算之前排序。如果对于标量
    对象的副作用相对于对同一标量对象的另一个副作用或使用同一个标量对象的值的值计算
    是不确定的,则该行为未确定。



因为您有多个操作对同一标量对象产生副作用,彼此之间,你处于未定义行为的领域,甚至 999 将是允许的输出。


Possible Duplicate:
Undefined Behavior and Sequence Points

I'm not sure if this is a gcc bug or not, so I'll ask:

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

gcc gives the extremely strange result: "122" which AFAICT is impossible. Because << is left associative, it should be the same as:

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

and because there is a sequence point before and after evaluating arguments, n is never modified twice (or even accessed) between two sequence points -- so it shouldn't be undefined behaviour, just the order of evaluation unspecified.

So AFAICT valid results would be: 111 012 002 101

and nothing else

解决方案

There is a sequence point between evaluating arguments and calling a function. There is no sequence point between evaluating different arguments.

Let's look at the outermost function call:

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

The arguments are

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

and

  • ++n

It is unspecified which of these is evaluated first. It's also allowed that the first argument is partially evaluated when the second argument is evaluated.

From the standard, section [intro.execution] (wording from draft 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 different 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 undefined.

Because you have multiple operations with side effects on the same scalar object which are unsequenced with respect to each other, you're in that realm of undefined behavior, and even 999 would be a permissible output.

这篇关于意外的评估顺序(编译器错误?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆