简体   繁体   English

将一元运算符联合起来是否有意义?

[英]Does it make sense for unary operators to be associative?

The C++ operator precedence table from http://en.cppreference.com/w/cpp/language/operator_precedence (I know it's not normative, but the standard doesn't talk about precedence or associativity) marks unary operators as right/left associative. 来自http://en.cppreference.com/w/cpp/language/operator_precedence的C ++运算符优先级表(我知道它不是规范性的,但标准不讨论优先级或关联性)将一元运算符标记为右/左关联。

From a discussion on a different question, I'm left with doubts. 从对不同问题的讨论中,我对此表示怀疑。 Does it make sense for unary operators to be associative? 将一元运算符联合起来是否有意义?

It's just an artefact of the way that the associativity is derived from the grammar. 它只是从语法中得出关联性的方式的人工制品。

The reason that addition is left-associative is that one of the productions for additive-expression is additive-expression + multiplicative-expression , with the additive-expression on the left. 加法是左关联的原因是加法表达的产生之一加法表达 + 乘法表达 ,左边是加法表达式。 So when you see: 所以当你看到:

a + b + c

this must be equivalent to (a + b) + c , because the only way to match the production is with a + b as the additive-expression and c as the multiplicative-expression . 这必须等同于(a + b) + c ,因为匹配生产的唯一方法是使用a + b作为加法表达式 ,将c作为乘法表达式 a on its own is an additive-expression , but b + c is not a multiplicative-expression and so a + b + c doesn't match the production if we try to take a as the additive-expression . a本身是一个加法表达式 ,但是b + c不是乘法表达式 ,因此如果我们试图将a作为加法 表达式 ,则a + b + c与生成不匹配。

If you haven't before, I recommend that you read through the "Expressions" chapter ignoring the semantics: look only at the grammar productions. 如果你以前没有,我建议你阅读忽略语义的“表达式”一章:只看语法作品。 Then you'll see just how it is that precedence and associativity are defined by the grammar. 然后你会看到优先级和关联性是如何由语法定义的。 The big trick is that every "high-precedence" type of expression IS-A "lower-precedence" type of expression. 最大的诀窍是每个“高优先级”类型的表达式IS-A“低优先级”类型的表达式。 So every multiplicative-expression is an additive-expression , but not vice-versa, and this is what makes multiplication "bind tighter" than addition. 因此,每个乘法表达式都是一个加法表达式 ,但反之亦然,这就是使乘法“比绑定更紧”的原因。

Prefix unary operators are defined in the grammar like: unary-expression : ++ cast-expression and so on, with the operator on the left for prefix and on the right for postfix. 前缀一元运算符在语法中定义如: unary-expression :++ cast-expression等,左侧为运算符,前缀为运算符,右侧为后缀。 In other words, we "insert the parentheses" on the left for postfix and on the right for prefix. 换句话说,我们在左边插入括号“forfix”,在右边插入前缀。 That is, we can say that the grouping is left-to-right for postfix operators and right-to-left for prefix operators. 也就是说,我们可以说,对于后缀运算符,分组是从左到右,对于前缀运算符,从右到左分组。 And indeed the C++ standard says exactly that (5.2/1 and 5.3/1 in C++03). 事实上,C ++标准正是如此(C ++ 03中的5.2 / 1和5.3 / 1)。 It might be an abuse of terminology or at least a new coinage to refer to this unary grouping as "associativity". 可能是滥用术语或至少是一个新的造币来将这种一元分组称为“关联性”。 But it's not a major one since it's obvious what must be meant. 但它并不是一个重要因素,因为它显然必须具有什么意义。

The only difference here between binary and unary operators is that the syntax would still make sense if the binary operators grouped in the opposite direction, so a - b - c means a - (b - c) . 二元和一元运算符之间的唯一区别是,如果二元运算符按相反方向分组,语法仍然有意义,因此a - b - c表示a - (b - c) It would be surprising but would not otherwise affect the language. 这将是令人惊讶的,但不会影响语言。 With unary operators it would be more than surprising to group !!a as (!!)a , the language would also have to supply a meaning for the sub-expression !! 使用一元运算符将组合起来更令人惊讶!!a as (!!)a ,语言也必须为子表达式提供意义 !! , which currently it doesn't have. ,目前它没有。 A functional language could give it a meaning: !! 一种功能语言可以赋予它一个意义: !! might mean the function composed from ! 可能意味着由...组成的功能! and ! 而且! , ie the same operation as static_cast<bool>() , but C++ has no concept of composing functions or operators. ,即与static_cast<bool>()相同的操作,但C ++没有组成函数或运算符的概念。 The reason C++ doesn't need to supply that meaning is that ! C ++不需要提供这个含义的原因是! "groups right-to-left". “从右到左”。 Which (because of the big trick in the grammar) is just another way of saying that !! 哪个(因为语法中的大技巧)只是另一种说法!! is not a syntactically correct expression so is never a sub-expression of anything. 不是语法正确的表达式,所以永远不是任何东西的子表达式。

So yes, it does make sense to say that prefix operators group right-to-left and postfix operators group left-to-right. 所以,是的,它一定道理说,前缀操作员组从右到左,左到右的后缀操作员组。 But it's also "obvious" that it must be this way around, because of other things we know about the C++ language. 但是,由于我们了解C ++语言的其他事情,它也必须是这样“显而易见”。

Btw, I think that technically speaking in C++ at least, postfix ++ is not a unary operator. 顺便说一句,我认为从技术上讲,至少在C ++中,postfix ++ 不是一元运算符。 It's a postfix operator. 它是一个后缀运算符。 But that really doesn't matter except that it's the terminology in the standard, because obviously it is an operator and it has one operand, so is "unary" in English. 但这确实无关紧要,除非它是标准中的术语,因为很明显它是一个运算符,它有一个操作数,所以英语中的“一元”。

在一元运算符的情况下,运算符的相关性仅确定运算符出现在操作数的哪一侧。

Consider the following piece of code 考虑以下代码

int *p;
*p++;

The expression *p++ can be evaluated as either (*p)++ (incrementing the object that p points to) or *(p++) (pointing to the next object pointed by p). 表达式*p++可以被评估为(*p)++ (递增p指向的对象)或*(p++) (指向*(p++)指向的下一个对象)。

Because unary operators are right associative the expression *p++ will be evaluated as *(p++) . 因为一元运算符是右关联的,所以表达式*p++将被评估为*(p++) (I came up with this while reading Kernighan and Ritchie .) (我在读Kernighan和Ritchie时想出了这个。)

It seems that the precedence and associativity has been changed and postfix ++ has higher precedence than dereference * operator. 似乎优先级和关联性已经改变,并且postfix ++具有比dereference * operator更高的优先级。

According to C11 the above expression will be evaluated as *(p++) . 根据C11,上述表达式将被评估为*(p++)

I hope this makes it more clear why unary operators have associativity. 我希望这更清楚地说明为什么一元运算符具有相关性。

Thanks to Lucian Grigore for pointing this out. 感谢Lucian Grigore指出这一点。

Not sure, but if the following were valid, yes. 不确定,但如果以下是有效的,是的。

++i--

but as it isn't, and throws the error 但事实并非如此,并抛出错误

lvalue required as increment operand

All behaviour of the unary operator can be explained in terms of precedence only. 一元运算符的所有行为只能用优先级来解释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM