概述
C++ 運算符的優先權
優先權 | 名稱 | 運算符 | | 所需變數個數 | 結合性 |
1 | | :: | 否 | | 自左向右 |
2 | 成員訪問運算符 | . | 否 | | 自左向右 |
指向成員運算符 | -> | |
下標運算符 | [ ] | |
括弧 / 函式運算符 | () | | |
3 | 自增運算符 | ++ | | | 自右向左 |
自減運算符 | -- | |
按位取反運算符 | ~ | |
邏輯非運算符 | ! | |
正號 | + | |
負號 | - | |
取地址運算符 | & | |
地址訪問運算符 | * | |
| (Type) | |
類型長度運算符 | | 否 |
記憶體分配運算符 | new | |
取消分配記憶體運算符 | delete
| |
類型轉換運算符 | castname_cast<type> | 否 |
4 | 成員指針運算符 | .* | 否 | 雙目運算符 | 自左向右 |
->* | |
5 | 乘號 | * | | 雙目運算符 | 自左向右 |
除號 | / | |
取余運算符 | % | |
6 | 加號 | + | | 雙目運算符 | 自左向右 |
減號 | - | |
7 | 位左移運算符 | << | | 雙目運算符 | 自左向右 |
位右移運算符 | >> | |
8 | 小於號 | < | | 雙目運算符 | 自左向右 |
小於等於號 | <= | |
大於號 | > | |
大於等於號 | >= | |
9 | 等於號(判等運算符) | == | | 雙目運算符 | 自左向右 |
不等於號 | != | |
10 | | & | | 雙目運算符 | 自左向右 |
11 | | ^ | | 雙目運算符 | 自左向右 |
12 | | | | | 雙目運算符 | 自左向右 |
13 | 邏輯且 | && | | 雙目運算符 | 自左向右 |
14 | 邏輯或 | || | | 雙目運算符 | 自左向右 |
15 | | ? : | 否 | 三目運算符 | 自右向左 |
16 | 賦值運算符 | = | | 雙目運算符 | 自右向左 |
| += | |
-= | |
*= | |
/= | |
%= | |
<<= | |
>>= | |
&= | |
|= | |
^= | |
17 | 拋出異常運算符 | throw | 否 | | 自左向右 |
18 | | , | | 雙目運算符 | 自左向右 |
賦值
賦值語句的作用是把某個
常量或變數或
表達式的值賦值給另一個變數。符號為‘=’。這裡並不是等於的意思,只是賦值,等於用‘==’表示。
注意:賦值語句左邊的變數在程式的其他地方必須要聲明。
得已賦值的變數我們稱為
左值,因為它們出現在賦值語句的左邊;產生值的表達式我們稱為右值,因為它們出現在賦值語句的右邊。常數只能作為右值。
例如:
count=5;
total1=total2=0;
第一個賦值語句大家都能理解。
第二個賦值語句的意思是把0同時賦值給兩個變數。這是因為
賦值語句是從右向左運算的,也就是說從右端開始計算。這樣它先total2=0;然後total1=total2;那么我們這樣行不行呢?
(total1=total2)=0;
對於上面的表達式,先計算括弧中的部分,即將total2賦值給total1,然後賦值運算符將左側對象作為左值返回,即返回total1,然後對total1賦值為0。即:
total1=total2;
total2=0;
算術
符號
| +
| -
| *
| /
| +
| %
| -
|
功能
| 單目正
| 單目負
| 乘法
| 除法
| 加法
| 取余
| 減法
|
Area=Height*Width;
num=num1+num2/num3-num4;
運算符也有個運算順序問題,先算乘除再算加減。單目正和單目負最先運算。
取模運算符(%)用於計算兩個整數相除所得的餘數。例如:
a=7%4;
最終a的結果是3,因為7%4的餘數是3。
那么有人要問了,我要想求它們的商怎么辦呢?
b=7/4;
這樣b就是它們的商了,應該是1。
也許有人就不明白了,7/4應該是1.75,怎么會是1呢?這裡需要說明的是,當兩個整數相除時,所得到的結果仍然是整數,沒有小數部分。要想也得到小數部分,可以這樣寫7.0/4或者7/4.0,也即把其中一個數變為非整數。
那么怎樣由一個實數得到它的整數部分呢?這就需要用
強制類型轉換了。例如:
a=(int) (7.0/4);
因為7.0/4的值為1.75,如果在前面加上(int)就表示把結果
強制轉換成
整型,這就得到了1。那么思考一下a=(float) (7/4);最終a的結果是多少?
單目減運算符相當於取相反值,若是正值就變為負值,若是負數就變為正值。
單目加運算符沒有意義,純粹是和單目減構成一對用的。
邏輯
邏輯運算符是根據
表達式的值來返回真值或是假值。其實在C語言中沒有所謂的真值和假值,只是認為非0為真值,0為假值。
符號 功能
&& 邏輯與
當表達式進行&&運算時,只要有一個為假,總的表達式就為假,只有當所有都為真時,總的式子才為真。當表達式進行||運算時,只要有一個為真,總的值就為真,只有當所有的都為假時,總的式子才為假。邏輯非(!)運算是把相應的變數數據轉換為相應的真/假值。若原先為假,則邏輯非以後為真,若原先為真,則邏輯非以後為假。
還有一點很重要,當一個
邏輯表達式的後一部分的取值不會影響整個表達式的值時,後一部分就不會進行運算了。例如:
a=2,b=1;
a||b-1;
因為a=2,為真值,所以不管b-1是不是真值,總的
表達式一定為真值,這時後面的表達式就不會再計算了。
關係運算符
關係運算符是先對兩個
表達式進行比較,然後返回一個真/假值。
關係運算符
| 關係運算符的功能
|
>
| 大於
|
<
| 小於
|
>=
| 大或等於
|
<=
| 小或等於
|
==
| 等於
|
!=
| 不等於
|
這些運算符大家都能明白,主要問題就是關係運算符的等於 == 和賦值的等於 = 之間的區別了。
一些剛開始學習C語言和C++的新人總是因為弄不明白這兩個運算符之間的區別,經常在一些簡單問題上出錯,自己檢查時卻找不出錯誤的原因。 為了正確區分,請看下面的代碼:
if(Amount=123) ……
很多新人都理解為如果Amount等於123,就怎么樣。其實這行代碼的意思是先賦值Amount=123,然後判斷這個
表達式是不是真值,因為結果為 123,是真值,那么就做後面的。如果想讓當Amount等於123才運行時,應該修改為
if(Amount==123) ……
自增自減
這是一類特殊的運算符,自增運算符++和自減運算符--對變數的操作結果是增加1和減少1。例如:
--Couter;
Couter--;
++Amount;
Amount++;
看這些例子裡,運算符在前面還是在後面對本身的影響都是一樣的,都是加1或者減1,但是當把他們作為其他
表達式的一部分,兩者就有區別了。運算符放在變數前面,那么在運算之前,變數先完成自增或自減運算;如果運算符放在後面,那么自增自減運算是在變數參加表達式的運算後再運算。這樣講可能不太清楚,看下面的例子:
num1=4;
num2=8;
a=++num1;
b=num2++;
a =++num1;這總的來看是一個賦值,把++num1的值賦給a,因為自增運算符在變數的前面,所以num1先自增加1變為5,然後賦值給a,最終a也為5。b=num2++;這是把num2++的值賦給b,因為自增運算符在變數的後面,所以先把num2賦值給b,b應該為8,然後num2自增加1變為 9。
那么如果出現這樣的情況我們怎么處理呢?
c=num1+++num2;
到底是c=(num1++)+num2;還是c=num1+(++num2);這要根據
編譯器來決定,不同的編譯器可能有不同的結果。所以我們在以後的編程當中,應該儘量避免出現上面複雜的情況。
複合賦值
在賦值運算符當中,還有一類C/C++獨有的複合賦值運算符。它們實際上是一種縮寫形式,使得對變數的改變更為簡潔。
Total=Total+3;
乍一看這行代碼,似乎有問題,這是不可能成立的。其實還是老樣子,'='是賦值不是等於。它的意思是本身的值加3,然後在賦值給本身。為了簡化,上面的代碼也可以寫成:
Total+=3;
符號 功能
+= 加法賦值
-= 減法賦值
*= 乘法賦值
/= 除法賦值
%= 模運算賦值
<<= 左移賦值
>>= 右移賦值
&= 位邏輯與賦值
^= 位邏輯異或賦值
上面的十個複合賦值運算符中,後面五個我們到以後
位運算時再說明。
那么看了上面的
複合賦值運算符,有人就會問,到底Total=Total+3;與Total+=3;有沒有區別?答案是有的,對於A=A+1,
表達式A被計算了兩次,對於複合運算符A+=1,表達式A僅計算了一次。一般的來說,這種區別對於程式的運行沒有多大影響,但是當表達式作為函式的返回值時,函式就被調用了兩次(以後再說明),而且如果使用普通的
賦值運算符,也會加大程式的開銷,使效率降低。
條件
條件運算符(?:)是C語言中唯一的一個
三目運算符,它是對第一個
表達式作真/假檢測,然後根據結果返回另外兩個表達式中的一個。
<表達式1>?<表達式2>:<表達式3>
在運算中,首先對第一個表達式進行檢驗,如果為真,則返回表達式2的值;如果為假,則返回表達式3的值。
例如:
a=(b>0)?b:-b;
當b>0時,a=b;當b不大於0時,a=-b;這就是
條件表達式。其實上面的意思就是把b的絕對值賦值給a。
逗號
在C語言中,多個
表達式可以用逗號分開,其中用逗號分開的表達式的值分別結算,但整個表達式的值是最後一個表達式的值。
假設a=(b=2,c=7,d=5),
a1=(++b,c--,d+3);
a2=++b,c--,d+3;
對於第一行代碼,有三個表達式,用逗號分開,所以最終的值應該是最後一個表達式的值,也就是d+3,為8,所以a=8。對於第二行代碼,那么也是有三個表達式,這時的三個表達式為a2=++b、c--、d+3,(這是因為
賦值運算符比逗號
運算符優先權高)所以最終表達式的值雖然也為8,但a2=4。
還有其他的如位邏輯運算符,位移運算符等等,我們等到講
位運算時再說明。
優先結合
從上面的逗號運算符那個例子可以看出,這些運算符計算時都有一定的順序,就好象先要算乘除後算加減一樣。優先權和結合性是運算符兩個重要的特性,結合性又稱為計算順序,它決定組成
表達式的各個部分是否參與計算以及什麼時候計算。
下面是C語言中所使用的運算符的優先權和結合性:
優先權 運算符 結合性
(最高) () [] -> . 自左向右
! ~ ++ -- + - * & sizeof 自右向左
* / % 自左向右
+ - 自左向右
<< >> 自左向右
< <= > >= 自左向右
== != 自左向右
& 自左向右
^ 自左向右
| 自左向右
&& 自左向右
|| 自左向右
?: 自右向左
= += -= *= /= %= &= ^= |= <<= >>= 自右向左
(最低) , 自左向右