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

时间:2012-10-18 18:30:11

标签: c++ operators unary-operator associativity

来自http://en.cppreference.com/w/cpp/language/operator_precedence的C ++运算符优先级表(我知道它不是规范性的,但标准不讨论优先级或关联性)将一元运算符标记为右/左关联。

从对不同问题的讨论中,我有些疑惑。一元运算符是否合理是否有意义?

4 个答案:

答案 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

一元运算符的所有行为都只能用优先级来解释。