对一元运算如何产生此输出感到困惑

发布于 2024-12-02 02:48:29 字数 615 浏览 4 评论 0原文

可能的重复:
单个语句中的多个增量运算符
未定义的行为和序列点

有人可以向我解释一下为什么这行代码会生成这样的输出? 代码(将 i 和 j 都初始化为零后):

cout<<i++<<','<<++j<<','<<--i<<','<<j--<<'\n';

输出:

-1,0,0,0;

我知道 i++ 意味着先评估然后增加 1,而 ++i 意味着增加 1 然后评估。但不确定顺序 cout 语句中的多重求值是什么行为。

谢谢!

Possible Duplicates:
Multiple increment operators in single statement
Undefined Behavior and Sequence Points

can someone explain to me why this line of code generate such output?
code (after initilizeing both i&j to zero):

cout<<i++<<','<<++j<<','<<--i<<','<<j--<<'\n';

output:

-1,0,0,0;

I know i++ means evaluate first then increase by 1, while ++i means increase by 1 then evaluate. but not sure what behavior is the multiple evaluation in a sequenced cout statement.

thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

╰ゝ天使的微笑 2024-12-09 02:48:29

该代码的行为未定义。允许实现在 --i 之前或之后评估 i++,或者交错评估,使得最终结果看起来毫无意义。

对于优化器来说,这甚至是合法的,当遇到诸如

if( k != 0 ) {
   cout << i++ << --i;
}
foofum(k);

推理这样的代码时,因为 then 分支中的代码是未定义的行为,那么我们可以得出结论:k 始终为零,并将整个事情减少到

foofum(0);

(这将通过以下事实得到正式证明:对 i 的未排序更新的“未定义”行为可能碰巧将 0 分配给k 和跳跃到右大括号。未定义确实意味着任何事情都可能发生)。

只是不要编写这样的代码。

编辑:在现已删除的答案中建议,该语句的效果只是未指定,因为重载的 << 是函数调用而不是本机运算符。然而,就我们当前的目的而言,这只是使该语句等效于

f(g(i++), i--);

(这里 f 表示单参数 ostream::operator<<(),但AAA.f(BBB)f(AAA,BBB) 的评估顺序规则相同)。编译器可以决定计算 f 参数的顺序。如果它碰巧首先评估 i--,则评估顺序变为:

  • i--
  • i++
  • 序列点
  • 调用 g
  • 序列点
  • 调用 f

由于没有序列点分隔 i--i++,因此会导致未定义的行为。

另一方面,f(g(i+=h()), i++) 可以说只是在序列点形式主义下未指定。我认为它在 C++1x 的关系公式中恢复为未定义。

The behavior of that code is undefined. An implementation is allowed to evaluate i++ before --i, or after it, or to stagger the evaluations such that the end results seem to make no sense at all.

It's even legal for an optimizer, when faced with code such as

if( k != 0 ) {
   cout << i++ << --i;
}
foofum(k);

to reason that because the code in the then branch is undefined behavior, then we can conclude that k is always zero, and reduce the entire thing to

foofum(0);

(This would be formally justified by the fact that the "undefined" behavior of the unsequenced updates to i just might happen to be assigning 0 to k and jumping to the closing brace. Undefined really does mean anything can happen).

Just don't write code like that.

Edit: It was suggested in a now-deleted answer that the effect of the statement is merely unspecified because the overloaded <<'s are function calls rather than native operators. However, that just makes the statement equivalent, for our present purposes, to

f(g(i++), i--);

(here the f represents a one-argument ostream::operator<<(), but the rules for evaluation order for AAA.f(BBB) and f(AAA,BBB) are the same). The compiler can decide in which order it evaluates the arguments to f. If it happens to evaluate i-- first, the evaluation order becomes:

  • i--
  • i++
  • sequence point
  • call g
  • sequence point
  • call f

Since there is no sequence point separating i-- and i++, undefined behavior results.

On the other hand, f(g(i+=h()), i++) is arguably merely unspecified under the sequence-point formalism. I think it reverts to undefined in C++1x's relational formulation.

墨洒年华 2024-12-09 02:48:29

C/C++ 中函数参数的计算顺序是未指定
此处未指定参数传递给 << 的顺序,因此结果也是如此。

The order of evaluation of arguments to a function in C/C++ is Unspecified.
The order in which arguments are being passed to << is Unspecified here and hence the result.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文