返回语句后的序列点?
在我对这里的一个问题的回答中,我解释了当postfix ++在与return
语句相同的行上的全局变量上使用时发生了什么。
C11的资料性附录C表明在return
后立即有一个序列点,并参考规范性章节6.8.6.4,其中没有关于序列点的文本可以找到。
我可以在C标准中找到规范性文本,说明return
语句后有一个序列点吗?
(我只在7.1.4 / 3中找到了规范文本,用于库函数,作为一个特殊情况。)
C 2011(draft n1570)6.8 4:“以下各项都是完整的表达式:… 返回语句中的(可选)表达式。 在评估完整表达式和评估下一个要评估的完整表达式之间有一个序列点。“
因此从技术上讲,序列点不是在返回之后,而是在返回表达式和下一个表达式之间的评估之间。 考虑这个代码,当a
最初为0时调用:
int a = 0; int Foo(void) { return a++; } void Bar(void) { int b = Foo() + a; … }
在Foo() + a
,是否首先评估Foo()
或a
是否未指定。 我们将根据两个潜在规则考虑两个顺序( 返回后的序列点与返回表达式和下一个完整表达式之间的序列点)。 如果实现首先执行,那么它必须:
a Sequence point Foo() +
然后会有一些其他的完整表达式,因此,根据任一规则,都会有一个序列点,就我们而言,这个代码都是相同的。 结果是b
设置为0。
如果实现首先执行Foo()
,那么,使用“ 返回后的序列指针”规则,实现必须执行:
Sequence point Foo() Sequence point a +
此代码将定义行为: a
在Foo
由副作用递增,并且在访问a
之前完成,然后执行+
。 结果是a
被设置为1.虽然结果可能是0或1这个“ 返回后的序列点”规则,但仅仅未指定使用两个订单中的哪一个; 行为并非完全未定义。
但是,如果实现首先执行Foo()
并使用标准C规则“ 返回表达式和下一个完整表达式之间的序列点”,那么我们有:
Sequence point Foo() ??? a ??? + ???
“???”标记位于所需序列点可能位于返回之后和下一个完整表达式之前的任何位置。 在这种情况下,a的值可以在a
访问并在Foo()
修改,并且没有中间序列点。 那是未定义的行为。
因此,规则“ 返回表达之后和下一个完整表达之前的序列点”与“ 返回之后的序列点”不同; 第一个在这个例子中有未定义的行为,第二个没有。
我认为你不会找到你想要的东西。 no text regarding sequence points can be found
是真的,它仅在第6.8节第4节中暗示。
第1.9节(脚注11)中的C ++标准(ISO / IEC 14882:2003)规定了返回后的序列点未明确写入C标准中的任何位置:
11)函数返回的序列点没有在ISO C中明确指定,并且在全表达式中可以被认为是冗余的序列点,但是在C + +中额外的清晰度很重要。 在C ++中,被调用函数可以通过多种方式终止其执行,例如抛出exception。