小知识:C/C++ 标准没有定义过任何的运算符优先级!
C/C++ 的优先级顺序表,以及运算法的结合性,是为了方便C/C++程序员理解语法规则,从标准指定的语言文法(表达式部分)中推导出来的。
实际上,标准指定的语言文法有一部分是无法通过优先级顺序表表示出来的。
- 一个就是对
sizeof(unsigned)-1的文法分析; - 另一个就是对
p1<p2 ? p1=NULL : p2=NULL,或者说b ? p1 : p2 = nullptr的文法分析。
标准指定的语言文法保证了语言不会出现歧义:
- sizeof 的运算数不能是类型转型:表达式
sizeof(unsigned)-1无歧义地转译成(sizeof(unsigned)) - 1,而非sizeof((unsigned)-1)。 - 三元和赋值运算符的“相对优先级”在 C 与 C++ 不太一样,而且在 C 中会有一些实现与标准之间的差异:
- C 标准指定的语言文法中,赋值不允许在三元运算符的右侧,故
e = a < d ? a++ : a = d不能通过分析。 - 许多 C 编译器使用修改的文法,其中 ?: 拥有高于 = 的优先级,这分析成
e = ( ((a < d) ? (a++) : a) = d )(之后编译失败,因为 C 中 ?: 决不是左值而 = 要求左值在左侧)。 - C++ 标准指定的语言文法中, ?: 和 = 拥有相等的优先级并从右到左成组,故而
e = a < d ? a++ : a = d分析为e = ((a < d) ? (a++) : (a = d))。
- C 标准指定的语言文法中,赋值不允许在三元运算符的右侧,故
附标准中的相关文法:
1. C89 - 3.3.3 Unary operators - Syntax
unary-expression:
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )
unary-operator: one of
& * + - ~ !
C89 - 3.3.4 Cast operators - Syntax
cast-expression:
unary-expression
( type-name ) cast-expression
其他 C/C++ 标准基本都是这样。
如 C18 的草案 N2176 以及 C++17 的草案 N4659:


2. C89 - 3.3.15 Conditional operator - Syntax
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
解释:
logical-OR-expression 是一个优先级最低到 || 的表达式。
expression 是一个优先级最低到 , 的表达式。
因为三元运算符右边,最低优先级允许递归的使用三元运算符,所以赋值不允许在三元条件运算符的右侧。
3. C++17 - 8.3 Unary expressions

解释
assignment-expression 是一个优先级最低到 x= 的表达式。所以C++赋值允许在三元条件运算符的右侧。
附表达式文法顺序:#primary-expression -> #postfix-expression -> #unary-expression -> cast-expression -> multiplicative-expression -> additive-expression -> shift-expression -> relational-expression -> equality-expression -> AND-expression -> exclusive-OR-expression -> inclusive-OR-expression -> logical-AND-expression -> logical-OR-expression -> #conditional-expression -> $assignment-expression -> expression
浙公网安备 33010602011771号