计划1:
#include <iostream>
using namespace std;
int a = 5;
int fun1() {
a = 17;
return 3;
}
int main() {
// Even though C languages are left associative,
// this line of code evaluates fun1() first:
a = a + fun1();
// a = 17+3
printf("%d",a);
a = fun1()+a;
printf("\n%d",a);
return 0;
}
输出
20
20
计划2:
int a = 10;
int fun(){
a= 15;
return 30;
}
int main(void) {
// whereas in this example, fun() is evaluated last:
int x = a + 10 + fun();
// x = 10 + 10 + 30
a= 10;
int y = fun() + 10 + a;
printf(" x = %d \n y = %d \n",x,y);
return 0;
}
输出
x = 50
y = 55
为什么程序1首先评估fun1()而在程序2中,fun()最后在表达式结束时进行评估?
根据我的理解,基于C语言是关联的,为什么程序1表现得很奇怪?
答案 0 :(得分:3)
历史上,未指定函数调用的参数评估顺序。这意味着对于电话
foo(bar(), baz());
如果它需要调用bar()
而不是baz()
,或者反过来需要调用编译器。请记住,调用运算符是泛型函数调用的另一种情况,即baz() + bar()
在语义上与operator+(baz(), bar())
相同。
出于实际目的,编译器用于评估从倒数到第一个的参数,因为这是将参数推送到堆栈以用于许多函数调用ABI的顺序。
答案 1 :(得分:2)
你混合了两个概念(虽然它经常发生),让我们看一下表达式:
a = b + c + d * e;
运算符优先级和关联性意味着该表达式等于
a = ( ( b + c ) + ( d * e ) );
但并不意味着,d * e
必须在b + c
之前进行评估,因为*具有更高的优先级。详情请见order of evaluation
重点是我的。除了下面提到的,C ++中没有从左到右或从右到左评估的概念。这不应与运算符的从左到右和从右到左的关联性混淆:表达式f1()+ f2()+ f3()被解析为(f1()+ f2())+ f3( )由于operator +的左右关联性,但是f3的函数调用可以在运行时的第一个,最后一个或f1()或f2()之间进行评估。
答案 2 :(得分:0)
有三个独立的概念经常混淆:
评估顺序,用于确定评估操作数的顺序。
标准中通常没有指定。
优先顺序,它决定首先评估两个运算符中的哪一个。
例如,在a + b * c
中,在加法之前评估乘法
操作数的评估顺序不受优先级的影响。
关联性,它决定首先评估哪个运算符具有相同的优先级。
例如,<<
是左关联的; a << b << c
被评估为(a << b) << c
,而赋值是右关联的; a = b = c
是a = (b = c)
操作数的评估顺序也不受关联性的影响。
答案 3 :(得分:-2)
此类型的评估顺序未按标准指定。由编译器来完成他正在进行的优化。