“立即在库函数返回之前"序列点的结果是什么? [英] What's the consequence of a sequence-point "immediately before a library function returns"?

查看:44
本文介绍了“立即在库函数返回之前"序列点的结果是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近的问题中,某些代码显示为具有未定义的行为:

In this recent question, some code was shown to have undefined behavior:

a[++i] = foo(a[i-1], a[i]);

因为即使 foo()的实际 call 是一个序列点,所以赋值未排序,因此您不知道该函数是在 ++ i 发生副作用之后还是在此之前被调用的.

because even though the actual call of foo() is a sequence point, the assignment is unsequenced, so you don't know whether the function is called after the side-effect of ++i took place or before that.

对此有进一步的考虑,函数调用中的顺序点仅保证在输入函数后执行副作用来评估函数自变量,例如

Thinking further about this, the sequence point at a function call only guarantees that side effects from evaluating the function arguments are carried out once the function is entered, e.g.

int y = 1;
int func1(int x) { return x + y; }
int main(void)
{
    int result = func1( y++ ); // guaranteed to be 3
}

但是查看标准,还有§7.1.4p3 (在有关标准库的章节中):

But looking at the standard, there's also §7.1.4 p3 (in the chapter about the standard library):

在库函数返回之前有一个序列点.

There is a sequence point immediately before a library function returns.

我的问题是:本段的结果是什么?为什么它只涉及库函数,实际上将依赖哪种类型的代码?

My question here is: What's the consequence of this paragraph? Why does it only concern library functions and what kind of code would actually rely on that?

简单的想法,例如(无用的代码)

Simple ideas like (nonsensical code to follow)

errno = 0;
long result = ftell(file) * errno;

此时仍将是不确定的,乘法是无序列的.我正在寻找一个示例,该示例利用此特殊保证§7.1.4p3为库函数提供了帮助.

would still be undefined as this time, the multiplication is unsequenced. I'm looking for an example that makes use of this special guarantee §7.1.4 p3 makes for library functions.

关于建议的重复项,返回语句后的顺序点?,这确实是密切相关的,我在之前就找到了问这个问题.它不是重复的,因为

Regarding the suggested duplicate, Sequence point after a return statement?, this is indeed closely related and I found it before asking this question. It's not a duplicate, because

  • 它询问在 return 之后立即有一个规范点的规范文本,而,而没有询问返回的结果.
  • 它仅提及库函数的特殊规则.此问题是关于此问题的,未作进一步阐述.
  • it asks about normative text stating there is a sequence point immediately after a return, without asking about the consequences when there is one.
  • it only mentions the special rule for library functions this question is about, without further elaborating on it.

因此,我的问题在那儿没有得到回答.接受的答案使用未排序表达式中的返回值(在本例中为 addition ),并解释结果如何取决于此加法的顺序,只有在知道了的情况下才能找到该>加法的排序,整个结果将在 return 之后立即用一个序列点定义.它没有显示由于该规则而实际定义的代码示例,也没有说明库函数的特殊性.

Consequently, my questions here are not answered over there. The accepted answer uses a return value in an unsequenced expression (in this case an addition) and explains how the result depends on the sequencing of this addition, only finding that if you knew the sequencing of the addition, the whole result would be defined with a sequence point immediately after return. It doesn't show an example of code that is actually defined because of this rule, and it doesn't say anything about how/why library functions are special.

推荐答案

库函数没有实现标准所涵盖的实现它们的代码(它们甚至可能无法在C中实现).该标准仅指定其行为.因此,有关 return 语句的规定不适用于库函数的实现.

Library functions don't have the code that implements them covered by the standard (they might not even be implemented in C). The standard only specifies their behaviour. So the provision about return statements does not apply to implementation of library functions.

此子句的目的(结合在库函数的入口处有一个序列点)是指库函数的任何副作用都在可能在库中的任何其他评估之前或之后进行排序.调用库函数的代码.

The purpose of this clause (in combination with there being a sequence point on entry of a library function) is to say that any side-effects of the library functions are sequenced either before or after any other evaluations that might be in the code which calls the library function.

所以问题中的示例不是未定义的行为(除非乘法溢出!): errno 的读取是在 ftell 修改之前或之后进行的,尚不清楚.

So the example in your question is not undefined behaviour (unless the multiplication overflows!): the read of errno is either sequenced before or after the modification by ftell, it's unspecified which.

这篇关于“立即在库函数返回之前"序列点的结果是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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