下面的表格列出了C运算符的优先级和相关性。运算符列表从上到下,优先级逐步降低。
Precedence |
Operator |
Description |
Associativity |
1 |
++ -- |
Suffix/postfix increment and decrement |
Left-to-right |
() |
Function call |
||
[] |
Array subscripting |
||
. |
Structure and union member access |
||
-> |
Structure and union member access through pointer |
||
(type){list} |
Compound literal(C99) |
||
2 |
++ -- |
Prefix increment and decrement |
Right-to-left |
+ - |
Unary plus and minus |
||
! ~ |
Logical NOT and bitwise NOT |
||
(type) |
Cast |
||
* |
Indirection (dereference) |
||
& |
Address-of |
||
sizeof |
Size-of |
||
_Alignof |
Alignment requirement(C11) |
||
3 |
* / % |
Multiplication, division, and remainder |
Left-to-right |
4 |
+ - |
Addition and subtraction |
|
5 |
<< >> |
Bitwise left shift and right shift |
|
6 |
< <= |
For relational operators < and ≤ respectively |
|
> >= |
For relational operators > and ≥ respectively |
||
7 |
== != |
For relational = and ≠ respectively |
|
8 |
& |
Bitwise AND |
|
9 |
^ |
Bitwise XOR (exclusive or) |
|
10 |
| |
Bitwise OR (inclusive or) |
|
11 |
&& |
Logical AND |
|
12 |
|| |
Logical OR |
|
13 |
?: |
Ternary conditional |
Right-to-left |
14 |
= |
Simple assignment |
|
+= -= |
Assignment by sum and difference |
||
*= /= %= |
Assignment by product, quotient, and remainder |
||
<<= >>= |
Assignment by bitwise left shift and right shift |
||
&= ^= |= |
Assignment by bitwise AND, XOR, and OR |
||
15 |
, |
Comma |
Left-to-right |
备注:
-
前缀 ++ 和 -- 的操作数不能是类型转换。这条规则在语法上禁止了一些在语义上无效的表达式。有些编译器会忽略这条规则,而从语义上检测其无效性。
(The operand of prefix ++ and -- can't be a type cast. This rule grammatically forbids some expressions that would be semantically invalid anyway. Some compilers ignore this rule and detect the invalidity semantically.)
-
sizeof 的操作数不能是类型转换:表达式 sizeof (int) * p 可以明确地解释为 (sizeof(int)) * p,但不能解释为 sizeof((int)*p) 。* 而不是 sizeof((int)*p)。 (The operand of sizeof can't be a type cast: the expression sizeof (int) * p is unambiguously interpreted as (sizeof(int)) * p, but not sizeof((int)*p).)
-
条件运算符中间(?和:之间)的表达式被当作括号来解析:它相对于?:的优先级被忽略。(The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored.)
-
赋值运算符的左操作数必须是一元表达式(第二级运算符,不包括cast运算符)。这条规则在语法上禁止了一些在语义上无效的表达式。许多编译器会忽略这条规则,而从语义上检测其无效性。例如,e = a < d ? a++ : a = d 就是一个因该规则而无法解析的表达式。然而,许多编译器会忽略这条规则,将其解析为 e = ( ((a < d) ? (a++) : a) = d ),然后给出一个错误,因为它在语义上是无效的。
(Assignment operators' left operands must be unary (level-2 non-cast) expressions. This rule grammatically forbids some expressions that would be semantically invalid anyway. Many compilers ignore this rule and detect the invalidity semantically. For example, e = a < d ? a++ : a = d is an expression that cannot be parsed because of this rule. However, many compilers ignore this rule and parse it as e = ( ((a < d) ? (a++) : a) = d ), and then give an error because it is semantically invalid.)
在解析表达式时,列在某一行的运算符将比列在其下一行的运算符与其参数绑定得更紧(就像用括号绑定一样)。例如,表达式 *p++ 将被解析为 *(p++),而不是 (*p)++。
(When parsing an expression, an operator which is listed on some row will be bound tighter (as if by parentheses) to its arguments than any operator that is listed on a row further below it. For example, the expression *p++ is parsed as *(p++), and not as (*p)++.)
同一单元格中的运算符(一个单元格中可能列出多行运算符)按给定的方向以相同的优先级进行运算。例如,表达式 a=b=c 被解析为 a=(b=c),而不是 (a=b)=c,这是因为从右到左的关联性。
(Operators that are in the same cell (there may be several rows of operators listed in a cell) are evaluated with the same precedence, in the given direction. For example, the expression a=b=c is parsed as a=(b=c), and not as (a=b)=c because of right-to-left associativity.)
说明(Notes)
优先级和关联性与计算顺序无关。(Precedence and associativity are independent from order of evaluation.)
标准本身并没有规定优先级。它们是从语法中派生出来的。(The standard itself doesn't specify precedence levels. They are derived from the grammar.)
在 C++ 中,条件运算符( conditional operator,即a?b:c )的优先级与赋值运算符相同,前缀 ++,-- 和赋值运算符对操作数没有限制。(In C++, the conditional operator has the same precedence as assignment operators, and prefix ++ and -- and assignment operators don't have the restrictions about their operands.)
关联性规范对于一元操作符来说是多余的,只是为了完整起见才显示出来:一元前缀操作符总是从右向左关联(sizeof ++*p 就是 sizeof(++(*p))),而一元后缀操作符总是从左向右关联(a[1][2]++ 是 ((a[1])[2])++ )。请注意,关联性对于成员访问运算符是有意义的,即使它们与一元后缀运算符组合在一起:a.b++ 被解析为 (a.b)++ 而不是 a.(b++)。
(Associativity specification is redundant for unary operators and is only shown for completeness: unary prefix operators always associate right-to-left (sizeof ++*p is sizeof(++(*p))) and unary postfix operators always associate left-to-right (a[1][2]++ is ((a[1])[2])++). Note that the associativity is meaningful for member access operators, even though they are grouped with unary postfix operators: a.b++ is parsed (a.b)++ and not a.(b++).)
常用运算符
Common operators |
||||||
assignment |
increment decrement |
arithmetic |
logical |
comparison |
member access |
other |
a = b a += b a -= b a *= b a /= b a %= b a &= b a |= b a ^= b a <<= b a >>= b |
++a --a a++ a-- |
+a -a a + b a - b a * b a / b a % b ~a a & b a | b a ^ b a << b a >> b |
!a a && b a || b |
a == b a != b a < b a > b a <= b a >= b |
a[b] *a &a a->b a.b |
a(...) a, b (type) a a ? b : c sizeof _Alignof (since C11) |
References
* C17 standard (ISO/IEC 9899:2018):
* A.2.1 Expressions
* C11 standard (ISO/IEC 9899:2011):
* A.2.1 Expressions
* C99 standard (ISO/IEC 9899:1999):
* A.2.1 Expressions
* C89/C90 standard (ISO/IEC 9899:1990):
* A.1.2.1 Expressions
参考:
1,C Operator Precedence