运算符的结合性是什么?为什么它很重要?

102

什么是运算符的结合性,为什么它很重要?

10个回答

130

对于操作符,结合性指的是当相同的操作符在一行中出现时,我们首先应用哪个操作符。在下面的示例中,设 Q 为该操作符。

a Q b Q c

如果Q是左结合的,那么它会按照以下方式进行求值

(a Q b) Q c

如果它是右结合的,那么它会被评估为

a Q (b Q c)

这很重要,因为它改变了表达式的含义。考虑整数算术中的除法运算符,它是左关联的。

4 / 2 / 3    <=>    (4 / 2) / 3    <=> 2 / 3     = 0
如果它是右结合的,那么它将被解析为未定义的表达式,因为您将会除以零。
4 / 2 / 3    <=>    4 / (2 / 3)    <=> 4 / 0     = undefined

1
你知道如何找到给定语法的结合性,无论它是左结合还是右结合吗? - user2510115
2
例如 expr -> expr + term; 是左结合的,而 expr -> term + expr 是右结合的。 - C--
17
在您的回答的第一行中,与其说“当出现相同的运算符”,不如说“当具有相同优先级的运算符出现”。例如:a * b / c => 其中 * 和 / 具有相同的优先级。 - 1O1
2
@1O1 谢谢,但是如果具有相同优先级的运算符具有不同的结合性会发生什么?如果 * 是左结合的,但 / 是右结合的,那么 a * b / c 会如何计算?这时就会产生矛盾。因此,我认为如果您想涵盖多个运算符,需要说“当具有相同优先级和结合性的运算符”才行。 - Johannes Schaub - litb
2
@Mark 我不知道,但我想不出它应该如何工作。可能值得提一个额外的Stack Overflow问题。 - Johannes Schaub - litb
显示剩余2条评论

14

有三种结合性:

数学中的结合律

编程语言中的运算优先级

CPU高速缓存中的关联性

数学中的结合律是指像加法(+)这样的运算符所具有的一种属性。该属性允许您重新排列括号而不改变语句的值,即:

(a + b) + c = a + (b + c)
在编程语言中,操作符的结合性(或者称为优先级)是一个属性,用于确定在缺少括号的情况下,具有相同优先级的操作符如何分组;即每个操作符的计算顺序。这可能在编程语言之间存在差异。
在CPU高速缓存中,关联性是一种优化性能的方法。

4
运算符的结合性(或优先级)是一个属性,它确定相同优先级的运算符在没有括号的情况下如何分组。这句话非常完美,让我理解了。 - Rafael Eyng

10

简单!!

Left Associative means we evaluate our expression from left to right

Right Associative means we evaluate our expression from right to left 

我们知道乘号(*)、除号(/)和取模运算符(%)具有相同的优先级,但根据结合性,答案可能会有所不同:

例如:我们有表达式:4 * 8 / 2 % 5

Left associative:   (4 * 8) / 2 % 5 ==> (32 / 2) % 5 ==> 16 % 5 ==> 1

Right associative:  4 * 8 /(2 % 5) ==>  4 * ( 8 / 2) ==> 4 * 4 ==> 16

2
答案似乎有错误:2%5的计算结果是2,而不是0 - Caleb Stanford

10

这是同一优先级运算符的评估顺序。从左到右或从右到左的顺序很重要。

3 - 2 - 1

如果是从左到右,那么它就是

(3 - 2) - 1

如果它是从左到右的,那么它就是0。如果它是从右到左的,则为

3 - (2 - 1)

这是第二点。在大多数语言中,我们说减号运算符具有从左到右的结合性。

2020年更新:

关于3-2-1的情况可能看起来微不足道,如果说“当然,我们会从左到右进行计算”。但在其他情况下,比如在Ruby或NodeJS中进行计算:

$ irb
2.6.3 :001 > 2 ** 3 ** 2
 => 512 
**是“乘方”运算符。它的结合性是从右向左的。
 2 ** (3 ** 2)

这个是2 ** 9,即512,而不是

(2 ** 3) ** 2

这是 8 ** 2,即64


6

这是操作数与运算符绑定的顺序。基本上:

a - b + c

可能被计算为(假设-和+具有相同的优先级):

((a - b) + c) 或者,
(a - (b + c))

如果运算符是左结合的(立即绑定到左操作数),它将被计算为第一个。如果它们是右结合的,则将其计算为第二个。


6
如果您提到“运算符结合性”,那么它是指语言在缺少括号的情况下如何确定相同优先级的运算符分组的方式。
例如,在基于C的语言中,+和-运算符具有相同的优先级。当您编写一个使用它们两个的表达式(没有括号)时,编译器必须确定评估它们的顺序。
如果您写12 - 5 + 3,则可能的计算包括:
1. (12 - 5) + 3 = 10 2. 12 - (5 + 3) = 4
根据您评估表达式的顺序,您可以得到不同的结果。在基于C的语言中,+和-具有左结合性,这意味着上面的表达式将被评估为第一种情况。
所有编程语言都有严格定义的运算符优先级和结合性规则。您可以在此处了解更多关于C#规则的信息。维基百科上已经很好地介绍了运算符结合性优先级的概念。

如果您的示例都使用相同的操作数,那么它们会更清晰明了。 - Michael Carman
如果在一个表达式中出现了两个具有相同优先级的运算符,但其中一个是左结合性,另一个是右结合性,并且没有使用括号进行区分,会发生什么情况?它会只使用首先找到的运算符的结合性吗? - Hector
这是不可能的,因为相同的优先级意味着相同的结合性。如果不是这种情况,就会存在模棱两可的情况,威胁到现实的存在。 - Ankur S

2

如果你指的是运算符结合性:

它定义了表达式被解析的方式。它提供了一个标准,以便每个表达式都以相同的方式被解析。

这对于具有相同优先级的操作非常重要,当可能存在副作用时尤其重要。


1
我们都知道优先级很重要,但在解释表达式的含义时结合性也非常重要。如果您想要一个真正简单的介绍,请尝试运算符的力量

1

大多数之前的示例都使用了常量。如果参数恰好是函数调用,那么调用的顺序可能由关联规则确定,当然这取决于您的编译器。如果这些函数具有副作用..


1
关联性是编程语言概念中计算顺序的一部分。计算顺序决定表达式的含义。它有两个主要规则:
1. 优先级规则 2. 关联性规则
优先级规则定义不同类型的“相邻”操作符的计算顺序。每种编程语言都有自己的运算符优先级表。
回到关联性,它定义了具有相同优先级的相邻操作的执行顺序。它有三种类型:
- 左关联性 - 右关联性 - 非关联性
如果一个操作符是左关联性的,则从左到右计算,同样,如果它是右关联性的,则从右到左计算。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接