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