来自http://en.cppreference.com/w/cpp/language/operator_precedence的C ++运算符优先级表(我知道它不是规范性的,但标准不讨论优先级或关联性)将一元运算符标记为右/左关联。
从对不同问题的讨论中,我有些疑惑。一元运算符是否合理是否有意义?
答案 0 :(得分:9)
这只是结语从语法中衍生出来的一种人工制品。
添加为左关联的原因是 additive-expression 的一个产品是 additive-expression + 乘法表达式,左边是加法表达式。所以当你看到:
a + b + c
这必须等同于(a + b) + c
,因为匹配作品的唯一方法是使用a + b
作为 additive-expression 和c
作为< EM>乘法表达。 a
本身就是 additive-expression ,但b + c
不是 multiplicative-expression ,因此a + b + c
不会如果我们尝试将a
作为 additive-expression ,则匹配生产。
如果你以前没有,我建议你阅读忽略语义的“表达式”一章:只看语法作品。然后你会看到如何是由语法定义的优先级和结合性。最大的诀窍是每个“高优先级”类型的表达式IS-A“低优先级”类型的表达式。因此,每个乘法表达式都是加法表达式,但反之亦然,这就是使乘法“绑定得比加法更紧”的原因。
前缀一元运算符在语法中定义如下:一元表达式:++ cast-expression 等等,左边的运算符用于前缀和on后缀的权利。换句话说,我们在左边插入括号“forfix”,在右边插入前缀。也就是说,我们可以说,对于后缀运算符,分组是从左到右,对于前缀运算符,从右到左分组。事实上,C ++标准正是如此(C ++ 03中的5.2 / 1和5.3 / 1)。可能是滥用术语或至少是一个新的造币来将这种一元分组称为“关联性”。但它并不是一个主要因素,因为它显然必须具有什么意义。
二元和一元运算符之间的唯一区别是,如果二元运算符按相反方向分组,语法仍然有意义,因此a - b - c
表示a - (b - c)
。这将是令人惊讶的,但不会影响语言。使用一元运算符将!!a
分组为(!!)a
会更令人惊讶,该语言还必须为子表达式!!
提供含义,目前它没有。函数式语言可以赋予它一个含义:!!
可能意味着函数由!
和!
组成,即与static_cast<bool>()
相同的操作,但C ++没有编写的概念功能或操作员。 C ++不需要提供这种含义的原因是!
“从右到左”。哪个(因为语法中的大技巧)只是另一种说法!!
不是语法正确的表达式所以永远不是任何东西的子表达式。
所以是的,确实有意义地说前缀运算符从右到左分组,后缀运算符从左到右分组。但是,由于我们了解C ++语言的其他事情,它也必须是这样“显而易见”。
顺便说一句,我认为从技术上讲,至少在C ++中,postfix ++
不是一元运算符。它是一个后缀运算符。但这确实无关紧要,除非它是标准中的术语,因为很明显它是一个运算符并且它有一个操作数,因此在英语中是“一元”。
答案 1 :(得分:2)
在一元运算符的情况下,运算符的关联性只决定运算符出现在操作数的哪一侧。
答案 2 :(得分:2)
考虑以下代码
int *p;
*p++;
表达式*p++
可以被评估为(*p)++
(递增p指向的对象)或*(p++)
(指向p指向的下一个对象)。
因为一元运算符是右关联的,所以表达式*p++
将被评估为*(p++)
。 (我在阅读 Kernighan和Ritchie 时想到了这一点。)
似乎优先级和关联性已更改,并且后缀++
的优先级高于取消引用*
运算符。
根据C11,上述表达式将被评估为*(p++)
。
我希望这能更清楚地说明为什么一元运算符具有相关性。
感谢Lucian Grigore指出这一点。
答案 3 :(得分:1)
不确定,但如果以下内容有效,是的。
++i--
但是因为它不是,并抛出错误
lvalue required as increment operand
一元运算符的所有行为都只能用优先级来解释。