運算符優先順序
運算符優先順序
在一個表達式中可能包含多個有不同運算符連接起來的、具有不同數據類型的數據對象;由於表達式有多種運算,不同的結合順序可能得出不同結果甚至出現錯誤運算錯誤,因為當表達式中含多種運算時,必須按一定順序進行結合,才能保證運算的合理性和結果的正確性、唯一性。
優先順序從上到下依次遞減,最上面具有最高的優先順序,逗號操作符具有最低的優先順序。表達式的結合次序取決於表達式中各種運算符的優先順序。優先順序高的運算符先結合,優先順序低的運算符后結合,同一行中的運算符的優先順序相同。
每種同類型的運算符都有內部的運算符優先順序,不同類型的運算符之間也有相應的優先順序順序。一個表達式中既可以包括相同類型的運算符,也可以包括不同類型的運算符或者函數。當多種運算符出現在同一個表達式中時,應該先按照不同類型運算符間的優先順序進行運算。各種運算符間的優先順序如下:數值運算符、字元串運算符、關係運算符、邏輯運算符。可以用括弧改變優先順序順序,使得括弧內的運算優先於括弧外的運算。對於多重括弧,總是由內到外強製表達式的某些部分優先運行。括弧內的運算總是最優先計算。
優先順序與求值順序無關。如a+b && b*c,雖然*優先順序最高,但這個表達式求值順序是從左到右。
優先順序從上到下依次遞減,最上面具有最高的優先順序,逗號操作符具有最低的優先順序。
相同優先順序中,按結合性進行結合。大多數運算符結合性是從左到右,只有三個優先順序是從右至左結合的,它們是單目運算符、條件運算符、賦值運算符。
基本的優先順序需要記住:
指針最優,單目運算優於雙目運算。如正負號。
先算術運算,后移位運算,最後位運算。請特別注意:1 << 3 + 2 & 7等價於 (1 << (3 + 2))&7.
邏輯運算最後結合。
優先順序 | 運算符 | 名稱或含義 | 使用形式 | 結合方向 | 說明 |
1 | [] | 數組下標 | 數組名[整型表達式] | 左到右 | |
() | 圓括弧 | (表達式)/函數名(形參表) | |||
. | 成員選擇(對象) | 對象。成員名 | |||
-> | 成員選擇(指針) | 對象指針->成員名 | |||
2 | - | 負號運算符 | -算術類型表達式 | 右到左 | 單目運算符 |
(type) | 強制類型轉換 | (純量數據類型)純量表達式 | |||
++ | 自增運算符 | ++純量類型可修改左值表達式 | 單目運算符 | ||
-- | 自減運算符 | --純量類型可修改左值表達式 | 單目運算符 | ||
* | 取值運算符 | *指針類型表達式 | 單目運算符 | ||
& | 取地址運算符 | &表達式 | 單目運算符 | ||
! | 邏輯非運算符 | !純量類型表達式 | 單目運算符 | ||
~ | 按位取反運算符 | ~整型表達式 | 單目運算符 | ||
sizeof | 長度運算符 | sizeof 表達式 sizeof(類型) | |||
3 | / | 除 | 表達式/表達式 | 左到右 | 雙目運算符 |
* | 乘 | 表達式*表達式 | 雙目運算符 | ||
% | 餘數(取模) | 整型表達式%整型表達式 | 雙目運算符 | ||
4 | + | 加 | 表達式+表達式 | 左到右 | 雙目運算符 |
- | 減 | 表達式-表達式 | 雙目運算符 | ||
5 | << | 左移 | 整型表達式<<整型表達式 | 左到右 | 雙目運算符 |
>> | 右移 | 整型表達式>>整型表達式 | 雙目運算符 | ||
6 | > | 大於 | 表達式>表達式 | 左到右 | 雙目運算符 |
>= | 大於等於 | 表達式>=表達式 | 雙目運算符 | ||
< | 小於 | 表達式<表達式 | 雙目運算符 | ||
<= | 小於等於 | 表達式<=表達式 | 雙目運算符 | ||
7 | == | 等於 | 表達式==表達式 | 左到右 | 雙目運算符 |
!= | 不等於 | 表達式!= 表達式 | 雙目運算符 | ||
8 | & | 按位與 | 整型表達式&整型表達式 | 左到右 | 雙目運算符 |
9 | ^ | 按位異或 | 整型表達式^整型表達式 | 左到右 | 雙目運算符 |
10 | | | 按位或 | 整型表達式|整型表達式 | 左到右 | 雙目運算符 |
11 | && | 邏輯與 | 表達式&&表達式 | 左到右 | 雙目運算符 |
12 | || | 邏輯或 | 表達式||表達式 | 左到右 | 雙目運算符 |
13 | ?: | 條件運算符 | 表達式1? 表達式2: 表達式3 | 右到左 | 三目運算符 |
14 | = | 賦值運算符 | 可修改左值表達式=表達式 | 右到左 | |
/= | 除后賦值 | 可修改左值表達式/=表達式 | |||
*= | 乘后賦值 | 可修改左值表達式*=表達式 | |||
%= | 取模后賦值 | 可修改左值表達式%=表達式 | |||
+= | 加后賦值 | 可修改左值表達式+=表達式 | |||
-= | 減后賦值 | 可修改左值表達式-=表達式 | |||
<<= | 左移后賦值 | 可修改左值表達式<<=表達式 | |||
>>= | 右移后賦值 | 可修改左值表達式>>=表達式 | |||
&= | 按位與后賦值 | 可修改左值表達式&=表達式 | |||
^= | 按位異或后賦值 | 可修改左值表達式^=表達式 | |||
|= | 按位或后賦值 | 可修改左值表達式|=表達式 | |||
15 | , | 逗號運算符 | 表達式,表達式,… | 左到右 | 從左向右順序結合 |
說明:
同一優先順序的運算符,結合次序由結合方向所決定。
簡單記就是:! > 算術運算符 > 關係運算符 > && > || > 賦值運算符
運算符 | 描述 | 例子 | 可重載性 |
第一級別 | |||
:: | 作用域解析符 | Class::age = 2; | 不可重載 |
第二級別 | |||
() | 函數調用 | isdigit('1') | 可重載 |
() | 成員初始化 | c_tor(int x, int y) : _x(x), _y(y*10){}; | 可重載 |
[] | 數組數據獲取 | array[4] = 2; | 可重載 |
-> | 指針型成員調用 | ptr->age = 34; | 可重載 |
. | 對象型成員調用 | obj.age = 34; | 不可重載 |
++ | 后自增運算符 | for( int i = 0; i < 10; i++ ) cout << i; | 可重載 |
-- | 后自減運算符 | for( int i = 10; i > 0; i-- ) cout << i; | 可重載 |
const_cast | 特殊屬性轉換 | const_cast | 不可重載 |
dynamic_cast | 特殊屬性轉換 | dynamic_cast | 不可重載 |
static_cast | 特殊屬性轉換 | static_cast | 不可重載 |
reinterpret_cast | 特殊屬性轉換 | reinterpret_cast | 不可重載 |
typeid | 對象類型符 | cout « typeid(var).name(); cout « typeid(type).name(); | 不可重載 |
第三級別(具有右結合性) | |||
! | 邏輯取反 | if( !done ) … | 可重載 |
not | ! 的另一種表達 | ||
~ | 按位取反 | flags = ~flags; | 可重載 |
compl | ~的另一種表達 | ||
++ | 預自增運算符 | for( i = 0; i < 10; ++i ) cout << i; | 可重載 |
-- | 預自減運算符 | for( i = 10; i > 0; --i ) cout << i; | 可重載 |
- | 負號 | int i = -1; | 可重載 |
+ | 正號 | int i = +1; | 可重載 |
* | 指針取值 | int data = *intPtr; | 可重載 |
& | 值取指針 | int *intPtr = &data; | 可重載 |
new | 動態元素內存分配 | long *pVar = new long; MyClass *ptr = new MyClass(args); | 可重載 |
new [] | 動態數組內存分配 | long *array = new long[n]; | 可重載 |
delete | 動態析構元素內存 | delete pVar; | 可重載 |
delete [] | 動態析構數組內存 | delete [] array; | 可重載 |
(type) | 強制類型轉換 | int i = (int) floatNum; | 可重載 |
sizeof | 返回類型內存 | int size = sizeof floatNum; int size = sizeof(float); | 不可重載 |
第四級別 | |||
->* | 類指針成員引用 | ptr->*var = 24; | 可重載 |
.* | 類對象成員引用 | obj.*var = 24; | 不可重載 |
第五級別 | |||
* | 乘法 | int i = 2 * 4; | 可重載 |
/ | 除法 | float f = 10.0 / 3.0; | 可重載 |
% | 取餘數(模運算) | int rem = 4 % 3; | 可重載 |
第六級別 | |||
+ | 加法 | int i = 2 + 3; | 可重載 |
- | 減法 | int i = 5 - 1; | 可重載 |
第七級別 | |||
<< | 位左移 | int flags = 33 << 1; | 可重載 |
>> | 位右移 | int flags = 33 >> 1; | 可重載 |
第八級別 | |||
< | 小於 | if( i < 42 ) … | 可重載 |
<= | 小於等於 | if( i <= 42 ) ... | 可重載 |
> | 大於 | if( i > 42 ) … | 可重載 |
>= | 大於等於 | if( i >= 42 ) ... | 可重載 |
第九級別 | |||
== | 恆等於 | if( i == 42 ) ... | 可重載 |
eq | == 的另一種表達 | ||
!= | 不等於 | if( i != 42 ) … | 可重載 |
not_eq | !=的另一種表達 | ||
第十級別 | |||
& | 位且運算 | flags = flags & 42; | 可重載 |
bitand | &的另一種表達 | ||
第十一級別 | |||
^ | 位異或運算 | flags = flags ^ 42; | 可重載 |
xor | ^的另一種表達 | ||
第十二級別 | |||
| | 位或運算 | flags = flags | 42; | 可重載 |
bitor | |的另一種表達 | ||
第十三級別 | |||
&& | 邏輯且運算 | if( conditionA && conditionB ) … | 可重載 |
and | &&的另一種表達 | ||
第十四級別 | |||
|| | 邏輯或運算 | if( conditionA || conditionB ) ... | 可重載 |
or | ||的另一種表達 | ||
第十五級別(具有右結合性) | |||
? : | 條件運算符 | int i = (a > b) ? a : b; | 不可重載 |
第十六級別(具有右結合性) | |||
= | 賦值 | int a = b; | 可重載 |
+= | 加賦值運算 | a += 3; | 可重載 |
-= | 減賦值運算 | b -= 4; | 可重載 |
*= | 乘賦值運算 | a *= 5; | 可重載 |
/= | 除賦值運算 | a /= 2; | 可重載 |
%= | 模賦值運算 | a %= 3; | 可重載 |
&= | 位且賦值運算 | flags &= new_flags; | 可重載 |
and_eq | &= 的另一種表達 | ||
^= | 位異或賦值運算 | flags ^= new_flags; | 可重載 |
xor_eq | ^=的另一種表達 | ||
|= | 位或賦值運算 | flags |= new_flags; | 可重載 |
or_eq | |=的另一種表達 | ||
<<= | 位左移賦值運算 | flags <<= 2; | 可重載 |
>>= | 位右移賦值運算 | flags >>= 2; | 可重載 |
第十七級別 | |||
throw | 異常拋出 | throw EClass(“Message”); | 不可重載 |
第十八級別 | |||
, | 逗號分隔符 | for( i = 0, j = 0; i < 10; i++, j++ ) … | 可重載 |
運算符 | 結合性 |
[ ] . ( ) (方法調用) | 從左向右 |
! ~ ++ -- +(一元運算) -(一元運算) | 從右向左 |
* / % | 從左向右 |
+ - | 從左向右 |
<< >> >>> | 從左向右 |
< <= > >= instanceof | 從左向右 |
== != | 從左向右 |
& | 從左向右 |
^ | 從左向右 |
| | 從左向右 |
&& | 從左向右 |
|| | 從左向右 |
?: | 從右向左 |
= | 從右向左 |
一個特殊的例子:
public class stlye
{
public static void main(String[] args)
{
int a=10,b=6;
System.out.println("改變之前的數:a="+a+",b="+b);
a-=b++;
System.out.println("改變之後的數:a="+a+",b="+b);
}
}
運算結果為:
改變之前的數:a=10,b=6
改變之後的數:a=4,b=7
因為b++運算中先執行++,再返回後置++運算表達式(b++)的返回值(6)給-=運算符。
在這個程序中a-=b++等於a=a-b++=10-6,所以a=4。
優先順序 | 類別 | 運算符 |
1 | 基本 | (x) x.y f(x) a[x] x++ x-- new typeof sizeof checked unchecked |
2 | 單目 | + - ! ~ ++x --x (T)x |
3 | 乘法與除法 | * / % |
4 | 加法與減法 | + - |
5 | 移位運算 | << >> |
6 | 關係運算 | < > <= >= |
7 | 條件等 | == != |
8 | 位邏輯與 | & |
9 | 位邏輯異或 | ^ |
10 | 位邏輯或 | | |
11 | 條件與 | && |
12 | 條件或 | ‖ |
13 | 條件 | ?: |
14 | 賦值 | = |
一個特殊的例子:
class Program
{
static void Main(string[] args)
{
int a; a = 10; int b = 4;
a += b++;
Console.WriteLine("a={0}",a);
Console.WriteLine("b={0}", b);
Console.ReadLine();
}
}
運算結果為:
a=14
b=5
在這個程序中a+=b等於a=a+b=10+4,因為 b++ 時返回了一個臨時變數后才進行自增。
優先順序 | 類別 | 運算符 |
1 | 乘方 | ^ |
2 | 取負 | - |
3 | 乘 | * |
3 | 除 | / |
4 | 四捨五入除/位移 | \ |
5 | 取模 | Mod |
6 | 加 | + |
6 | 減 | - |
7 | 字元串合併 | & 或 + |
8 | 相等 | = |
8 | 大於 | > |
8 | 大於等於 | >= |
8 | 小於 | < |
8 | 小於等於 | <= |
8 | 不等於 | <> |
8 | 同類對象 | Is |
8 | Like運算 | Like |
9 | 非 | Not |
10 | 與 | And |
11 | 或 | Or |
12 | 異或 | Xor |
13 | 邏輯等 | Eqv |
14 | 邏輯大於等於(蘊含) | Imp |