此问题已在此处有答案:
Who defines operator precedence and associativity, and how does it relate to order of evaluation?(6个回答)
What is the order of evaluation for function arguments?(6个回答)
20天前关闭。
在下面的表达式中,函数调用的顺序是什么:
a = f1(23, 14) * f2(12/4) + f3();
它依赖于编译器吗?
5条答案
按热度按时间wlsrxk511#
在C和C++中,每个操作数的求值顺序是unspecified,这意味着,在您的情况下,函数调用的顺序是 unspecified。
请注意,它是 unspecified,notimplementation-defined*。
qjp7pelc2#
它在C和C++中都是Unspecified。
参考文献:
C++03标准:第5节:表达式,帕拉4:
除非另有说明[例如,&&和的特殊规则||],各个运算符的操作数和各个表达式的子表达式的求值顺序,以及副作用发生的顺序,为未指定。
C99标准:第6.5节:
操作符和操作数的分组由语法表示。72)除了后面指定的(对于函数call(),&&,||、?:和逗号运算符),子表达式的求值顺序和副作用发生的顺序都是未指定的。
ev7lccsx3#
C++:标准保证在到达序列点之前,所有在序列点之前遇到的表达式都被求值。在本例中,
=
和;
之间没有序列点,因此顺序未指定。cqoc49vn4#
在这种情况下,顺序无法预测。它不依赖于编译器,它是未指定的;即使使用相同的编译器,你也可以得到不同的求值顺序。
e5nqia275#
不要只是说这是未指定的,故事结束,让我解释一下如何评估这一点。最重要的是,不要混淆运算符优先级(operator precedence)和运算符求值顺序(order of evaluation)的概念,它们是不同的概念。
f1(23, 14) * f2(12/4)
将首先被求值,然后其结果将成为与f3()
相加的操作数,最后结果将被分配给a
。a = ( (f1(23, 14) * f2(12/4)) + f3() );
。f1(23, 14) * f2(12/4)
。运算对象本身的 * 求值顺序 * 是 * 未指定的行为 *,这意味着我们无法知道f1或f2运算对象是否首先被求值。编译器可以自由地按照从左到右或从右到左的方式计算它们,并且不需要记录哪种方式适用。我们所知道的是,编译器将一致地评估从左到右或从右到左。f1(23, 14)
将首先被评估。接下来的问题是,函数的哪个参数将首先被计算。同样的事情也适用于这里,函数参数的求值顺序也是未指定的。在这种情况下,这并不重要,因为两个参数都是整数常量。a
。这里学到的重要教训是:由于子表达式的求值顺序未指定,因此每个子表达式不应包含任何依赖于求值顺序的副作用。在这个例子中,如果f1和f2都将数字1或2分别写入一个全局变量,那么如果编译器从左到右求值,该全局变量的值最终将为2,但如果它从右到左求值,则该全局变量的值最终将为1。这样的代码在一个编译器上可以完美地工作,但在另一个编译器上却会悲惨地崩溃。