基于 C 的语言中从右到左和从左到右关联性的后果是什么?

发布于 2024-12-29 10:40:20 字数 351 浏览 1 评论 0原文

我正在编写脚本语言,我想复制(相当标准化的)C 操作顺序。< /a>

我从未牢牢掌握作为一个正式概念的一件事是关联性。为什么有些运算符组是从左到右,而另一些是从右到左?

有人能给我举几个例子,说明如果规则都是从左到右或与原来相反的话,一行代码看起来会有什么不同吗?或者为什么关联性是这样的,因为在我看来这只是一个任意的选择,但我认为他们这样做是有原因的。

另外,请注意,我确实知道关联性意味着什么,我只是想不出任何从左到右(或反之亦然)比其他选择更好的例子

I'm in the process of writing a scripting language and I want to copy the (pretty well standardized) C order of operations.

One thing that I never had a firm grasp of as a formal concept though is associativity. Why are some operator groups left-to-right and others right-to-left?

Can someone give me a few examples of how a line of code could look different if the rules were all left-to-right or the opposite of what they were? Or why the associativity is the way it is, as it seems to me just a arbitrary choice, but I assume they had a reason for it.

Also, just to note, I do know what associativity means, I just can't think of any examples where left-to-right (or vice-versa) is better than the other choice

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

卸妝后依然美 2025-01-05 10:40:20

在大多数情况下,每个运算符都具有对该运算符最有意义的结合性。

所有非赋值二元运算符都具有从左到右的结合性。这很有用,因为英语是从左到右阅读的,因此 x + y + z 的计算与其阅读方式一致。此外,对于算术运算符,其语义符合我们对数学中运算符的使用的期望。

赋值运算符具有从右到左的结合性。从左到右的赋值会产生奇怪且意想不到的语义。例如,x = y = z 将导致 x 具有 y 的原始值,而 y 具有z 的原始值。表达式完成后,预计所有三个变量将具有相同的值。

前缀一元运算符具有从右到左的关联性,这是有道理的,因为最接近操作数的运算符首先被求值,因此在 ~!x 中,!x 被求值首先,然后将 ~ 应用于结果。如果前缀运算符与从左到右的关联性一起应用,那真的非常非常奇怪:说 ~!x 意味着评估 ~x然后将 ! 应用于结果,这与我们对表达式的看法完全相反(或者至少与大多数人对表达式的看法...)。

For the most part, each operator has the associativity that makes the most sense for that operator.

All of the non-assignment binary operators have left-to-right associativity. This is useful for the obvious reason that English is read left-to-right and thus the evaluation of x + y + z is consistent with how it is read. In addition, for arithmetic operators, the semantics match what we expect from the usage of the operators in mathematics.

Assignment operators have right-to-left associativity. Left-to-right assignment would have bizarre and unexpected semantics. For example, x = y = z would result in x having the original value of y and y having the original value of z. It is expected that all three variables will have the same value after the expression is complete.

The prefix unary operators have right-to-left associativity, which makes sense because the operators closest to the operand are evaluated first, so in ~!x, !x is evaluated first, then ~ is applied to the result. It would be really, really weird were prefix operators applied with left-to-right associativity: to say that ~!x means evaluate ~x and then apply ! to the result is the complete opposite of how we think about expressions (or, at least, how most people think about expressions...).

晨敛清荷 2025-01-05 10:40:20

示例:

5 - 4 - 3
(5 - 4) - 3 = -2 // left association is correct
5 - (4 - 3) = 4  // right is incorrect

a == b == c // What does this equal?
            // It is common to have == be non-associative because of this.

x = y = z
x = (y = z) // right association is correct, sets x and y
(x = y) = z // left is incorrect, does not set y

大多数运算符从数学中继承了结合性。按位可以看作算术运算符,因此具有左结合性。

一元是右结合的,因为它以这种方式分组:

~!-x = ~(!(-(x))) 

除非后缀,否则其他方式没有多大意义。

Examples:

5 - 4 - 3
(5 - 4) - 3 = -2 // left association is correct
5 - (4 - 3) = 4  // right is incorrect

a == b == c // What does this equal?
            // It is common to have == be non-associative because of this.

x = y = z
x = (y = z) // right association is correct, sets x and y
(x = y) = z // left is incorrect, does not set y

Most operators inherit their associativity from math. Bitwise can be seen as arithmetic operators and thus have left associativity.

Unary is right associative because it groups that way:

~!-x = ~(!(-(x))) 

The other way wouldn't make much sense unless postfix.

幸福%小乖 2025-01-05 10:40:20

棘手的运算符是求幂(例如:Python 中的 **,R、haskell 中的 ^)。大多数语言、解析器等将 3 ** 3 ** 3 视为 3 ** (3 ** 3)。我个人认为这是正确的解释,但最近注意到 Octave 和 Matlab 都将其计算为 (3 ** 3) ** 3

这在 C 中不是问题,因为它没有求幂运算符。相反,您调用 pow 函数,并且必须显式声明 pow(3,pow(3,3))pow(pow(3,3) ),3)

The tricky operator is exponentiation (for example: ** in python, ^ in R, haskell). Most languages, parsers, etc view 3 ** 3 ** 3 as 3 ** (3 ** 3). I personally think this is the correct interpretation, but recently noticed that both octave and matlab compute this as (3 ** 3) ** 3.

This is not issue in C as it does not have an exponentiation operator. Instead you make calls to the pow function and have to explicitly state either pow(3,pow(3,3)) or pow(pow(3,3),3).

歌入人心 2025-01-05 10:40:20

累积舍入通常就是答案。

然而,>>和<<必须是它们本来的样子或结构如 12 << 2>> 3 不工作。

Accumulated roundoff is usually the answer.

However, >> and << have to be the way they are or constructs like 12 << 2 >> 3 don't work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文