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