return 语句后的序列点? [英] Sequence point after a return statement?

查看:26
本文介绍了return 语句后的序列点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我对问题的回答中 这里我解释了在与 return 语句在同一行的全局变量上使用后缀 ++ 时发生的情况.

In my answer to a question here I explained what happened when postfix ++ was used on a global variable on the same line as a return statement.

C11 的信息性附录 C 指出,在 return 之后有一个序列点,并参考规范性章节 6.8.6.4,其中没有关于序列点的文本.

The informative appendix C of C11 states that there is a sequence point immediately after a return and refers to normative chapter 6.8.6.4, where no text regarding sequence points can be found.

我在 C 标准的哪里可以找到规范文本,说明在 return 语句之后有一个序列点?

Where in the C standard can I find normative text stating that there is a sequence point after a return statement?

(我只在 7.1.4/3 找到了说明库函数的规范文本,作为一种特殊情况.)

(I only found normative text stating this for library functions, as a special case, at 7.1.4/3.)

推荐答案

C 2011 (draft n1570) 6.8 4: 以下每一个都是完整的表达式:……return 中的(可选)表达式声明.在完整表达式的求值和要求值的下一个完整表达式的求值之间存在一个序列点."

C 2011 (draft n1570) 6.8 4: "Each of the following is a full expression: … the (optional) expression in a return statement. There is a sequence point between the evaluation of a full expression and the evaluation of the next full expression to be evaluated."

所以从技术上讲,序列点不在 return 之后,而是在 return 中的表达式评估和下一个表达式之间.考虑这段代码,当 a 最初为 0 时调用:

So technically the sequence point is not after a return but is between the evaluation of the expression in the return and the next expression. Consider this code, called when a is initially 0:

int a = 0;

int Foo(void) { return a++; }

void Bar(void)
{
    int b = Foo() + a;
    …
}

Foo() + a 中,未指定首先评估 Foo() 还是 a.我们将根据两个潜在规则(return 之后的序列点与 return 表达式和下一个完整表达式之间的序列点)来考虑这两个顺序.如果实现首先执行a,那么它必须执行:

In Foo() + a, whether Foo() or a is evaluated first is unspecified. We will consider both orders in light of both potential rules (sequence point after return versus sequence point between the expression of the return and the next full expression). If the implementation does a first, then it must do:

a
Sequence point
Foo()
+

然后会出现其他一些完整的表达式,因此,根据任一规则,都会有一个序列点,就我们而言,无论哪种方式,这段代码都是相同的.结果是 b 设置为 0.

and then some other full expression would follow, so, by either rule, there would be a sequence point, and this code is the same either way, as far as we are concerned. The result is that b is set to 0.

如果实现首先执行Foo(),那么,使用return之后的序列点"规则,实现必须:

If the implementation does Foo() first, then, with the "sequence point after a return" rule, the implementation must do:

Sequence point
Foo()
Sequence point
a
+

此代码将具有定义的行为:aFoo 中的副作用递增,并且在访问 a 之前完成,然后执行+.结果是 a 被设置为 1.虽然根据return 之后的序列点"规则,结果可能是 0 或 1,但只是未指定两者中的哪一个使用订单;行为并非完全未定义.

This code would have defined behavior: a is incremented by the side effect in Foo, and that is complete before a is accessed, then + is performed. The result is that a is set to 1. Although the result may be 0 or 1 with this "sequence point after return" rule, it is merely unspecified which of the two orders is used; the behavior is not completely undefined.

但是,如果实现首先执行 Foo() 并使用标准 C 规则return 表达式和下一个完整表达式之间的序列点",那么我们有:

However, if the implementation does Foo() first and uses the standard C rule of "sequence point between the expression of a return and the next full expression", then we have:

Sequence point
Foo()
???
a
???
+
???

???"标记所需序列点可能位于的位置——return 之后和下一个完整表达式之前的任何位置.在这种情况下,a 的值可能会在 a 中访问并在 Foo() 中修改,并且没有中间序列点.那是未定义的行为.

The "???" mark places where the required sequence point might be—anywhere after the return and before the next full expression. In this case, the value of a might be accessed in a and modified in Foo(), and there is no intervening sequence point. That is undefined behavior.

因此,规则一个return之后的序列点和下一个完整的表达式之前"与一个return之后的序列点"是不同的;在此示例中,第一个具有未定义的行为,而第二个则没有.

Therefore, the rule "sequence point after the expression of a return and before next full expression" is different from "sequence point immediately after a return"; the first has undefined behavior in this example, and the second does not.

这篇关于return 语句后的序列点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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