7

在以下代码中:

int foo();
int bar();
int i;

i = foo() + bar();

foo是否由调用之前调用的C标准保证bar

4

5 回答 5

12

不, 没有序列点+。实际上,Wikipedia 页面上有一段关于它的引语可以回答您的问题:

考虑两个函数 f() 和 g()。在 C 和 C++ 中,+ 运算符不与序列点相关联,因此在表达式 f()+g() 中可能会先执行 f() 或 g()。

http://en.wikipedia.org/wiki/Sequence_points

于 2012-04-27T22:31:52.150 回答
7

未指定,在 C99 的情况下,相关报价为 6.5/3:

除非稍后指定(对于函数调用()&&||?:和逗号运算符),子表达式的求值顺序和副作用发生的顺序都是未指定的。

在您的示例中,foo()并且bar()是完整表达式的子表达式i = foo() + bar()

函数调用的“稍后”在这里并不直接相关,但作为参考,它是 6.5.2.2/10:

函数指示符、实际参数和实际参数中的子表达式的求值顺序未指定,但在实际调用之前有一个序列点。

因为&&它是 6.5.13/4:

与按位二进制 & 运算符不同,&& 运算符保证从左到右的求值;在对第一个操作数求值之后有一个序列点。

由于+不在顶部的运算符列表中,&&并且与+“不同”的方式相同,&&并且&“不同”,这正是您要问的问题。与, 不同&&+保证从左到右的评估。

于 2012-04-27T23:03:28.570 回答
2

不它不是。函数和运算符参数的求值顺序未定义。

该标准只说,调用foo并且bar不能交错,这可能在评估没有函数调用的子表达式时发生。

于 2012-04-27T22:31:36.453 回答
0

不,这没有定义。从K&R第200页:

表达式的求值顺序,除了某些例外,是未定义的,即使子表达式涉及副作用。也就是说,除非操作符的定义保证它的操作数以特定的顺序被评估,否则实现可以自由地以任何顺序评估操作数,甚至交错他们的评估。

K&R的第205页描述了加法运算符,并且没有定义两个操作数的求值顺序。

于 2012-04-27T22:35:16.123 回答
0

我工作的正确答案是“如果订单很重要,那么无论标准说什么会发生,代码都是不可维护的”。如果必须在 bar() 之前评估 foo(),请在 bar() 之前显式评估 foo()。这样做的基础不是每个程序员都知道标准,那些不知道原作者是否知道的程序员。

于 2012-04-27T23:55:28.980 回答