基于 C 的语言中从右到左和从左到右关联性的后果是什么?
我正在编写脚本语言,我想复制(相当标准化的)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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在大多数情况下,每个运算符都具有对该运算符最有意义的结合性。
所有非赋值二元运算符都具有从左到右的结合性。这很有用,因为英语是从左到右阅读的,因此 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 inx
having the original value ofy
andy
having the original value ofz
. 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...).示例:
大多数运算符从数学中继承了结合性。按位可以看作算术运算符,因此具有左结合性。
一元是右结合的,因为它以这种方式分组:
除非后缀,否则其他方式没有多大意义。
Examples:
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:
The other way wouldn't make much sense unless postfix.
棘手的运算符是求幂(例如: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
as3 ** (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 eitherpow(3,pow(3,3))
orpow(pow(3,3),3)
.累积舍入通常就是答案。
然而,>>和<<必须是它们本来的样子或结构如 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.