在下面的代码中:
int foo();
int bar();
int i;
i = foo() + bar();
C 标准是否保证在调用之前调用foo
bar
?
不,没有+
的序列点。维基百科页面上实际上有一段关于它的引用可以回答您的问题:
考虑两个函数 f(( 和 g((。在 C 和 C++ 中,+ 运算符不与序列点相关联,因此在表达式 f((+g(( 中,可能会首先执行 f(( 或 g((。
http://en.wikipedia.org/wiki/Sequence_points
它没有指定,在 C99 的情况下,相关报价为 6.5/3:
除非稍后指定(对于函数调用
()
、&&
、||
、?:
和 逗号运算符(,子表达式的求值顺序和 副作用发生的顺序均未指定。
在您的示例中,foo()
和 bar()
是完整表达式 i = foo() + bar()
的子表达式。
函数调用的"later"在这里没有直接关系,但作为参考,它是 6.5.2.2/10:
函数指示符的求值顺序,实际 参数和实际参数中的子表达式是 未指定,但在实际调用之前有一个序列点。
对于&&
,它是 6.5.13/4:
与按位二进制和运算符不同,&&&运算符保证 从左到右的评估;后面有一个序列点 第一个操作数的评估。
由于+
不在顶部的运算符列表中,因此&&
和+
"不像",就像&&
和&
"不像"一样,这正是您要问的事情。与&&
不同,+
不能保证从左到右的评估。
不,不是。函数和运算符参数的求值顺序未定义。
该标准仅规定,对foo
和bar
的调用不能交错,这在计算没有函数调用的子表达式时可能会发生。
不,这没有定义。 来自K&R第200页:
除某些例外情况外,表达式的计算顺序是未定义的,即使子表达式涉及副作用也是如此。 也就是说,除非运算符的定义保证其操作数按特定顺序计算,否则实现可以自由地以任何顺序计算操作数,甚至可以交错计算它们的计算。
K&R的第205页描述了加法运算符,并没有定义两个操作数的求值顺序。
我工作的正确答案是"如果顺序很重要,那么无论标准说会发生什么,代码都是不可维护的"。如果必须在 bar(( 之前计算 foo((,请在 bar(( 之前显式计算 foo((。这样做的基础不是每个程序员都知道标准,而那些知道标准的人不知道原作者是否知道。