运算符的优先级和结合性
运算符是告诉编译程序执行特定算术或逻辑操作的符号。
C语言的运算范围很宽,把除了控制语句和输入输出以外的几乎所有的基本操作都作为运算符处理。
主要分为三大类:算术运算符、关系运算符与逻辑运算符。
除此之外,还有一些用于完成特殊任务的运算符。
优先级:
C语言中,运算符的运算优先级共分为15级。1级最高,15级最低。
在表达式中,优先级较高的先于优先级较低的进行运算。
而在一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。
结合性:C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。
例如算术运算符的结合性是自左至右,即先左后右。
如有表达式x-y+z则y应先与"-"号结合,执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为"左结合性"。
而自右至左的结合方向称为"右结合性"。最典型的右结合性运算符是赋值运算符。
如x=y=z,由于“=”的右结合性,应先执行y=z再执行x=(y=z)运算。C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。
优先级 | 结合性 | 运算符 | 备注 |
---|---|---|---|
1 | 左结合 | () [] -> . | 圆括号 下标运算符 指向结构体成员运算符 结构体成员运算符 |
2 | 右结合 | ! ~ ++ -- + - (类型) * & sizeof | 逻辑非运算符 按位取反运算符 前缀增量运算符 前缀减量运算符 正号运算符 负号运算符 类型转换运算符 指针运算符 地址运算符 长度运算符 |
3 | 左结合 | * / % | 乘法运算符 除法运算符 取余运算符 |
4 | 左结合 | + - | 加法运算符 减法运算符 |
5 | 左结合 | << >> | 左移运算符 右移运算符 |
6 | 左结合 | < <= > >= | 关系运算符 |
7 | 左结合 | == != | 等于运算符 不等于运算符 |
8 | 左结合 | & | 按位与运算符 |
9 | 左结合 | ^ | 按位异或运算符 |
10 | 结合性 | | | 按位或运算符 |
11 | 左结合 | && | 逻辑与运算符 |
12 | 左结合 | || | 逻辑或运算符 |
13 | 右结合 | ? : | 条件运算符 |
14 | 右结合 | = += -= *= /= %= &= ^= |= <<= >>= | 赋值运算符 |
15 | 左结合 | , | 逗号运算符 |
优先级口诀:
口诀解释:
“圆方括号、箭头一句号”指的是第15级的运算符。
其中圆方括号很明显“()、[]”,箭头指的是指向结构体成员运算符“->”,句号指的是结构体成员运算符“.”。
“自增自减非反负、针强地址长度”指的是第14级的运算符。
其中非指的是逻辑运算符“!”,反指的是按位取反运算符“~”,负指的是负号运算符“-”,针指的是指针运算符“*”,
强指的是强制类型转换运算符,地址指的是地址运算符“&”,长度指的是长度运算符“sizeof”。
“乘除,加减,再移位”移位指的是左移运算符“<<”和右移运算符“>>”,其中除法还包括了取余运算符“%”。
“小等大等、等等不等”指的是第10级到第9级的运算符:<、<=、>和>=,等等指的是等于运算符==,不等指的是不等于运算符!=。
“八位与,七位异,六位或”其中 八位与指的是第8级的按位与运算符“&”,七位异指的是第7级的按位异或运算符“^”,六位或指的是第6级的按位或运算符“|”。
“五与,四或”指的是第5级、第4级的逻辑与运算符“&&”和逻辑或运算符“||”。
“三疑,二赋,一真逗”指的是第3级到第1级的运算符。
其中,三疑指的是条件运算符“?:”(三有双重含义:即指优先级别是三,它的运算符类型也是三目,疑也取“?”之意),
二赋指的是赋值运算符=、+=、-=、*=、/=、%=、>>=、<<=、&=、^=和|= ,
一真逗指的是第1级的“,”运算符,真字只是为了语句需要罢了。
由于C语言的运算符优先级与C++的不完全一样(主要是增加了几个运算符),所以这个口诀不能完全实用于C++.
但是应该能够兼容,大家可以比较一下他们的区别应该就能够很快掌握C++的优先级的!
当然,如果真的不想背这些优先级,那么可以在每次使用符号的地方都用上(),这样就不用在意运算符优先级了,这也是一个很好的编程习惯。
优先级
|
运算符
|
名称或含义
|
使用形式
|
结合方向
|
说明
|
1
|
[]
|
数组下标
|
数组名[常量表达式]
|
左到右
|
|
()
|
圆括号
|
(表达式)/函数名(形参表)
|
|||
.
|
成员选择(对象)
|
对象.成员名
|
|||
->
|
成员选择(指针)
|
对象指针->成员名
|
|||
2
|
-
|
负号运算符
|
-表达式
|
右到左
|
单目运算符
|
(类型)
|
强制类型转换
|
(数据类型)表达式
|
|||
++
|
自增运算符
|
++变量名/变量名++
|
单目运算符
|
||
--
|
自减运算符
|
--变量名/变量名--
|
单目运算符
|
||
*
|
取值运算符
|
*指针变量
|
单目运算符
|
||
&
|
取地址运算符
|
&变量名
|
单目运算符
|
||
!
|
逻辑非运算符
|
!表达式
|
单目运算符
|
||
~
|
按位取反运算符
|
~表达式
|
单目运算符
|
||
sizeof
|
长度运算符
|
sizeof(表达式)
|
|||
3
|
/
|
除
|
表达式/表达式
|
左到右
|
双目运算符
|
*
|
乘
|
表达式*表达式
|
双目运算符
|
||
%
|
余数(取模)
|
整型表达式/整型表达式
|
双目运算符
|
||
4
|
+
|
加
|
表达式+表达式
|
左到右
|
双目运算符
|
-
|
减
|
表达式-表达式
|
双目运算符
|
||
5
|
<<
|
左移
|
变量<<表达式
|
左到右
|
双目运算符
|
>>
|
右移
|
变量>>表达式
|
双目运算符
|
||
6
|
>
|
大于
|
表达式>表达式
|
左到右
|
双目运算符
|
>=
|
大于等于
|
表达式>=表达式
|
双目运算符
|
||
<
|
小于
|
表达式<表达式
|
双目运算符
|
||
<=
|
小于等于
|
表达式<=表达式
|
双目运算符
|
||
7
|
==
|
等于
|
表达式==表达式
|
左到右
|
双目运算符
|
!=
|
不等于
|
表达式!= 表达式
|
双目运算符
|
||
8
|
&
|
按位与
|
表达式&表达式
|
左到右
|
双目运算符
|
9
|
^
|
按位异或
|
表达式^表达式
|
左到右
|
双目运算符
|
10
|
|
|
按位或
|
表达式|表达式
|
左到右
|
双目运算符
|
11
|
&&
|
逻辑与
|
表达式&&表达式
|
左到右
|
双目运算符
|
12
|
||
|
逻辑或
|
表达式||表达式
|
左到右
|
双目运算符
|
13
|
?:
|
条件运算符
|
表达式1? 表达式2: 表达式3
|
右到左
|
三目运算符
|
14
|
=
|
赋值运算符
|
变量=表达式
|
右到左
|
|
/=
|
除后赋值
|
变量/=表达式
|
|||
*=
|
乘后赋值
|
变量*=表达式
|
|||
%=
|
取模后赋值
|
变量%=表达式
|
|||
+=
|
加后赋值
|
变量+=表达式
|
|||
-=
|
减后赋值
|
变量-=表达式
|
|||
<<=
|
左移后赋值
|
变量<<=表达式
|
|||
>>=
|
右移后赋值
|
变量>>=表达式
|
|||
&=
|
按位与后赋值
|
变量&=表达式
|
|||
^=
|
按位异或后赋值
|
变量^=表达式
|
|||
|=
|
按位或后赋值
|
变量|=表达式
|
|||
15
|
,
|
逗号运算符
|
表达式,表达式,…
|
左到右
|
从左向右顺序运算
|
C语言运算符优先级和口诀
一共有十五个优先级:
1 () [] . ->
2 ! ~ -(负号) ++ -- &(取变量地址)* (type)(强制类型) sizeof
3 * / %
4 + -
5 >> <<
6 > >= < <=
7 == !=
8 &
9 ^
10 |
11 &&
12 ||
13 ?:
14 = += -= *= /= %= |= ^= &= >>= <<=
15 ,
就着多吧 结合性:2 13 14 是从右至左 其他都是 从左至右
括号成员第一; //括号运算符[]() 成员运算符. ->
全体单目第二; //所有的单目运算符比如++、 --、 +(正)、 -(负) 、指针运算*、&乘除余三,加减四; //这个"余"是指取余运算即%
移位五,关系六; //移位运算符:<< >> ,关系:> < >= <= 等
等于(与)不等排第七; //即== 和!=
位与异或和位或; //这几个都是位运算: 位与(&)异或(^)位或(|)
"三分天下"八九十;
逻辑或跟与; //逻辑运算符:|| 和 &&
十二和十一; //注意顺序:优先级(||) 底于 优先级(&&)
条件高于赋值, //三目运算符优先级排到13 位只比赋值运算符和","高
逗号运算级最低! //逗号运算符优先级最低
C语言运算符优先级
优先级 |
运算符 |
名称或含义 |
使用形式 |
结合方向 |
说明 |
1 |
[] |
数组下标 |
数组名[常量表达式] |
左到右 |
-- |
() |
圆括号 |
(表达式)/函数名(形参表) |
-- |
||
. |
成员选择(对象) |
对象.成员名 |
-- |
||
-> |
成员选择(指针) |
对象指针->成员名 |
-- |
||
2 |
- |
负号运算符 |
-表达式 |
右到左 |
单目运算符 |
~ |
按位取反运算符 |
~表达式 |
|||
++ |
自增运算符 |
++变量名/变量名++ |
|||
-- |
自减运算符 |
--变量名/变量名-- |
|||
* |
取值运算符 |
*指针变量 |
|||
& |
取地址运算符 |
&变量名 |
|||
! |
逻辑非运算符 |
!表达式 |
|||
(类型) |
强制类型转换 |
(数据类型)表达式 |
-- |
||
sizeof |
长度运算符 |
sizeof(表达式) |
-- |
||
3 |
/ |
除 |
表达式/表达式 |
左到右 |
双目运算符 |
* |
乘 |
表达式*表达式 |
|||
% |
余数(取模) |
整型表达式%整型表达式 |
|||
4 |
+ |
加 |
表达式+表达式 |
左到右 |
双目运算符 |
- |
减 |
表达式-表达式 |
|||
5 |
<< |
左移 |
变量<<表达式 |
左到右 |
双目运算符 |
>> |
右移 |
变量>>表达式 |
|||
6 |
> |
大于 |
表达式>表达式 |
左到右 |
双目运算符 |
>= |
大于等于 |
表达式>=表达式 |
|||
< |
小于 |
表达式<表达式 |
|||
<= |
小于等于 |
表达式<=表达式 |
|||
7 |
== |
等于 |
表达式==表达式 |
左到右 |
双目运算符 |
!= |
不等于 |
表达式!= 表达式 |
|||
8 |
& |
按位与 |
表达式&表达式 |
左到右 |
双目运算符 |
9 |
^ |
按位异或 |
表达式^表达式 |
左到右 |
双目运算符 |
10 |
| |
按位或 |
表达式|表达式 |
左到右 |
双目运算符 |
11 |
&& |
逻辑与 |
表达式&&表达式 |
左到右 |
双目运算符 |
12 |
|| |
逻辑或 |
表达式||表达式 |
左到右 |
双目运算符 |
13 |
?: |
条件运算符 |
表达式1? 表达式2: 表达式3 |
右到左 |
三目运算符 |
14 |
= |
赋值运算符 |
变量=表达式 |
右到左 |
-- |
/= |
除后赋值 |
变量/=表达式 |
-- |
||
*= |
乘后赋值 |
变量*=表达式 |
-- |
||
%= |
取模后赋值 |
变量%=表达式 |
-- |
||
+= |
加后赋值 |
变量+=表达式 |
-- |
||
-= |
减后赋值 |
变量-=表达式 |
-- |
||
<<= |
左移后赋值 |
变量<<=表达式 |
-- |
||
>>= |
右移后赋值 |
变量>>=表达式 |
-- |
||
&= |
按位与后赋值 |
变量&=表达式 |
-- |
||
^= |
按位异或后赋值 |
变量^=表达式 |
-- |
||
|= |
按位或后赋值 |
变量|=表达式 |
-- |
||
15 |
, |
逗号运算符 |
表达式,表达式,… |
左到右 |
-- |
说明: 同一优先级的运算符,运算次序由结合方向所决定。
C++ 运算符优先级和关联性
C++ 语言包括所有 C 运算符并添加多个新的运算符。 运算符指定对一个或多个操作数执行的计算。
运算符优先级别指定包含多个运算符的表达式中的运算顺序。 运算符关联性指定,在包含多个具有相同优先级别的运算符的表达式中,操作数与其左侧还是右侧的操作数组合。 下表显示 C++ 运算符的优先级别和关联性(从最高优先级别到最低优先级别)。 优先级别编号相同的运算符具有等同的优先级别,除非由括号显式施加另一种关系。
运算符说明 |
运算符 |
---|---|
Group 1 precedence, no associativity |
|
:: |
|
Group 2 precedence, left to right associativity |
|
. or –> |
|
[ ] |
|
( ) |
|
++ |
|
–– |
|
typeid( ) |
|
const_cast |
|
dynamic_cast |
|
reinterpret_cast |
|
static_cast |
|
Group 3 precedence, right to left associativity |
|
sizeof |
|
++ |
|
–– |
|
~ |
|
! |
|
- |
|
+ |
|
& |
|
* |
|
new |
|
delete |
|
Cast: () |
|
Group 4 precedence, left to right associativity |
|
.* or –>* |
|
Group 5 precedence, left to right associativity |
|
* |
|
/ |
|
% |
|
Group 6 precedence, left to right associativity |
|
+ |
|
– |
|
Group 7 precedence, left to right associativity |
|
<< |
|
>> |
|
Group 8 precedence, left to right associativity |
|
< |
|
> |
|
<= |
|
>= |
|
Group 9 precedence, left to right associativity |
|
== |
|
!= |
|
Group 10 precedence left to right associativity |
|
& |
|
Group 11 precedence, left to right associativity |
|
^ |
|
Group 12 precedence, left to right associativity |
|
| |
|
Group 13 precedence, left to right associativity |
|
&& |
|
Group 14 precedence, left to right associativity |
|
|| |
|
Group 15 precedence, right to left associativity |
|
? : |
|
Group 16 precedence, right to left associativity |
|
= |
|
*= |
|
/= |
|
%= |
|
+= |
|
–= |
|
<<= |
|
>>= |
|
&= |
|
|= |
|
^= |
|
Group 17 precedence, right to left associativity |
|
throw |
|
Group 18 precedence, left to right associativity |
|
, |
http://www.cppreference.com/operator_precedence.html
Precedence | Operator | Description | Example | Associativity |
---|---|---|---|---|
1 | () [] -> . :: ++ -- |
Grouping operator Array access Member access from a pointer Member access from an object Scoping operator Post-increment Post-decrement |
(a + b) / 4; array[4] = 2; ptr->age = 34; obj.age = 34; Class::age = 2; for( i = 0; i < 10; i++ ) ... for( i = 10; i > 0; i-- ) ... |
left to right |
2 | ! ~ ++ -- - + * & (type) sizeof |
Logical negation Bitwise complement Pre-increment Pre-decrement Unary minus Unary plus Dereference Address of Cast to a given type Return size in bytes |
if( !done ) ... flags = ~flags; for( i = 0; i < 10; ++i ) ... for( i = 10; i > 0; --i ) ... int i = -1; int i = +1; data = *ptr; address = &obj; int i = (int) floatNum; int size = sizeof(floatNum); |
right to left |
3 | ->* .* |
Member pointer selector Member pointer selector |
ptr->*var = 24; obj.*var = 24; |
left to right |
4 | * / % |
Multiplication Division Modulus |
int i = 2 * 4; float f = 10 / 3; int rem = 4 % 3; |
left to right |
5 | + - |
Addition Subtraction |
int i = 2 + 3; int i = 5 - 1; |
left to right |
6 | << >> |
Bitwise shift left Bitwise shift right |
int flags = 33 << 1; int flags = 33 >> 1; |
left to right |
7 | < <= > >= |
Comparison less-than Comparison less-than-or-equal-to Comparison greater-than Comparison geater-than-or-equal-to |
if( i < 42 ) ... if( i <= 42 ) ... if( i > 42 ) ... if( i >= 42 ) ... |
left to right |
8 | == != |
Comparison equal-to Comparison not-equal-to |
if( i == 42 ) ... if( i != 42 ) ... |
left to right |
9 | & | Bitwise AND | flags = flags & 42; | left to right |
10 | ^ | Bitwise exclusive OR | flags = flags ^ 42; | left to right |
11 | | | Bitwise inclusive (normal) OR | flags = flags | 42; | left to right |
12 | && | Logical AND | if( conditionA && conditionB ) ... | left to right |
13 | || | Logical OR | if( conditionA || conditionB ) ... | left to right |
14 | ? : | Ternary conditional (if-then-else) | int i = (a > b) ? a : b; | right to left |
15 | = += -= *= /= %= &= ^= |= <<= >>= |
Assignment operator Increment and assign Decrement and assign Multiply and assign Divide and assign Modulo and assign Bitwise AND and assign Bitwise exclusive OR and assign Bitwise inclusive (normal) OR and assign Bitwise shift left and assign Bitwise shift right and assign |
int a = b; a += 3; b -= 4; a *= 5; a /= 2; a %= 3; flags &= new_flags; flags ^= new_flags; flags |= new_flags; flags <<= 2; flags >>= 2; |
right to left |
16 | , | Sequential evaluation operator | for( i = 0, j = 0; i < 10; i++, j++ ) ... | left to right |