Fid*_*its 26 c c++ operator-precedence associativity ansi-c
在C/C++的每本教科书中,您都可以找到运算符优先级和关联表,如下所示:

http://en.cppreference.com/w/cpp/language/operator_precedence
StackOverflow上的一个问题是这样的:
以下函数的执行顺序如下:
f1() * f2() + f3();
f1() + f2() * f3();
参考上面的图表,我自信地回答说函数具有从左到右的关联性,因此在前面的语句中,在这两种情况下都会像这样评估:
f1() - > f2() - > f3()
评估函数后,您完成评估,如下所示:
(a1*a2)+ a3
a1 +(a2*a3)
令我惊讶的是,很多人告诉我,我错了.决心证明他们错了,我决定转向ANSI C11标准.我再一次惊讶地发现在运算符优先级和关联性方面提到的很少.
Jos*_*eld 43
运算符优先级在适当的标准中定义.C和C++的标准是C和C++究竟是什么的唯一真实定义.所以,如果你仔细观察,细节就在那里.事实上,细节是语言的语法.例如,看看该语法产生式规则+和-在C++(统称为添加剂表达式):
additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression
Run Code Online (Sandbox Code Playgroud)
如您所见,乘法表达式是加法表达式的子规则.这意味着如果你有类似的东西x + y * z,y * z表达式是子表达式x + y * z.这定义了这两个运算符之间的优先级.
我们还可以看到,一个的左操作数添加剂表达扩展到另一添加剂的表达,这意味着与x + y + z,x + y是它的一个子表达式.这定义了关联性.
关联性确定如何对相同运算符的相邻使用进行分组.例如,+从左到右关联,这意味着x + y + z将按如下方式分组:(x + y) + z.
不要将此误认为是评估顺序.绝对没有理由z不能在之前计算出x + y值.重要的是它x + y是计算而不是y + z.
对于函数调用操作符,从左到右的关联性意味着f()()(f例如,如果返回了一个函数指针,可能会发生这种情况)被分组如下:( (f())()当然,另一个方向没有任何意义).
现在让我们考虑您正在考虑的示例:
f1() + f2() * f3()
Run Code Online (Sandbox Code Playgroud)
该*经营者具有比更高的优先级+运营商,所以表达式进行分组,如下所示:
f1() + (f2() * f3())
Run Code Online (Sandbox Code Playgroud)
我们甚至不必在这里考虑关联性,因为我们没有任何相同的运算符彼此相邻.
然而,对函数调用表达式的评估完全没有排序.f3然后f1,没有理由不能先被调用f2.在这种情况下,唯一的要求是在运算符之前评估运算符的操作数.因此,这将意味着f2和f3有前被称为*评估和*必须进行评估,并f1在之前必须调用+进行评估.
但是,有些运营商会对其操作数的评估进行排序.例如,in x || y,x总是在之前进行评估y.这允许短路,y如果x已知的话,不需要进行评估true.
之前在C和C++中使用序列点定义了评估顺序,并且两者都改变了术语以根据关系之前的顺序来定义事物.有关更多信息,请参阅未定义的行为和序列点.
oua*_*uah 10
语法表示C标准中运算符的优先级.
(C99,6.5p3)"运算符和操作数的分组由语法表示.74)"
74)"语法指定运算符在表达式求值中的优先级"
C99理由也说
"优先规则被编码为每个运算符的语法规则."
和
"关联性规则同样被编码为句法规则."
另请注意,关联性与评估顺序无关.在:
f1()*f2()+ f3()
函数调用以任何顺序进行评估.C语法规则表示这f1() * f2() + f3()意味着(f1() * f2()) + f3()但表达式中操作数的评估顺序是未指定的.
考虑优先级和关联性的一种方法是假设语言只允许包含赋值和一个运算符的语句,而不是多个运算符.所以声明如下:
a = f1() * f2() + f3();
Run Code Online (Sandbox Code Playgroud)
不允许,因为它有5个运算符:3个函数调用,乘法和加法.在这种简化的语言中,您必须将所有内容分配给临时对象,然后将它们组合在一起:
temp1 = f1();
temp2 = f2();
temp3 = temp1 * temp2;
temp4 = f3();
a = temp3 + temp4;
Run Code Online (Sandbox Code Playgroud)
关联性和优先级指定必须以该顺序执行最后两个语句,因为乘法具有比加法更高的优先级.但它没有指定前3个陈述的相对顺序; 做同样有效:
temp4 = f3();
temp2 = f2();
temp1 = f1();
temp3 = temp1 * temp2;
a = temp3 + temp4;
Run Code Online (Sandbox Code Playgroud)
sftrabbit给出了一个示例,其中函数调用运算符的关联性是相关的:
a = f()();
Run Code Online (Sandbox Code Playgroud)
当如上简化它时,这变为:
temp = f();
a = temp();
Run Code Online (Sandbox Code Playgroud)