C++:運算符

算術運算符(左結合律)

運算符 功能 用法 例子
+ 一元正號 + expr +1=1
- 一元負號 - expr -1=-1
* 乘法 expr * expr 4*4=16
/ 除法 expr / expr 9/3=3
% 求餘(取模) expr % expr 5%2=1
+ 加法 expr + expr 3+3=6
- 減法 expr - expr 10-2=8

邏輯和關係運算符

結合律 運算符 功能 用法 例子
! 邏輯非 !expr
< 小於 expr < expr
<= 小於等於 expr <= expr
> 大於 expr > expr
>= 大於等於 expr >= expr
== 相等 expr == expr
!= 不相等 expr != expr
&& 邏輯與 expr && expr
|| 邏輯或 expr || expr

賦值運算符和複合賦值運算符

遞增和遞減運算符

遞增運算符(++)和遞減運算符(--)爲對象的加1和減1 操作提供了一種簡潔的書寫形式。這兩個運算符還可應用於迭代器,因爲很多迭代器本身不支持算術運算,所以此時遞增和遞減運算符除了書寫簡潔外還是必須的。

遞增和遞減運算符有兩種形式:前置版本和後置版本。前置版本的運算符首先將運算對象加1(或減1),然後將改變後的對象作爲求值結果。後置版本也會將運算對象加1(或減1),但是求值結果是運算對象改變之前那個值的副本:

int i=0,j;
j=++i; //j=1,i=1:前置版本:j得到i遞增之後的值
j=i++; //j=1,i=2:後置版本:j得到i遞增之前的值

遞增和遞減運算符都必須作用於左值運算對象。前置版本將對象本身作爲左值返回,後置版本則將對象原始值的副本作爲右值返回。

建議:除非必要,否則不用遞增遞減運算符的後置版本。原因:前置版本的遞增運算符在把值加1後直接返回改變了的運算對象。與之相比,後置版本需要將原始值存儲下來以便於返回這個未修改的內容。如果我們不需要修改前的值,那麼後置版本的操作就是一種浪費。

解引用與取地址運算符

成員訪問運算符

點運算符(.)和箭頭運算符(->)都可以用於訪問類(結構)的成員,其中,點運算符獲取類對象的一個成員;箭頭運算符作用於一個指針類型的運算對象,其與點運算符有關,表達式:pointor->member等價於(*pointor).member(pointor是一個指針變量)。

string s="I'm a string!",*p=&s;
int n=s.size(); //運算string對象s的size成員
n=(*p).size();  //運行string類型指針p所指對象的size成員
n=p->size();    //等價於(*p).size()

因爲解引用運算符*的優先級低於點運算符.,所以執行解引用運算的子表達式兩端必須加上括號()。如果沒加括號,代碼的含義會大不相同:

//運行p的size成員,然後解引用size的結果,
//但由於p是一個指針,它是沒有名爲size的
//成員的,故此語句會無法通過編譯而出錯。
*p.size();

條件運算符

位運算符(左結合律)

運算符 功能 用法 例子
位求反 ~expr
<< 左移 expr1 << expr2
>> 右移 expr1 >> expr2
& 位與 expr1 & expr2
^ 位異或 expr1 ^ expr2
| 位或 expr1 | expr2

移位運算符(<<運算符和>>運算符)的內置含義是對其運算對象執行基於二進制位的移動操作,首先令左側運算對象的內容按照右側運算對象的要求移動指定位數,然後將經過移動的左側運算對象的拷貝作爲求值結果。其中,右側的運算對象一定不能爲負,而且值必須嚴格小於結果的位數,否則就會產生未定義的行爲。左移運算符(<<)在右側插入值爲0的二進制位。右移運算符(>>)的行爲則依賴於其左側運算對象的類型:如果該運算對象是無符號類型,在左側插入值爲0的二進制位;如果該運算對象是帶有符號類型,在左側插入符號位的副本或值爲0的二進制位,如何選擇要視具體環境而定。

位求反運算符(~)將運算對象逐位求反後生成一個新值,將1置爲0、將0置爲1。

位與(&)、位或(|)、位異或(^)運算符在兩個運算對象上逐位執行相應的邏輯操作。對於位與運算符(&)來說,如果兩個運算對象的對應位置都是1則運算結果中該位爲1,否則爲0。對於位或運算符(|)來說,如果兩個運算對象的對應位置至少有一個爲1則運算結果中該位爲1,否則爲0。對於位異或運算符(^)來說,如果兩個運算對象的對應位置有且只有一個爲1則運算結果中該位爲1,否則爲0。

運算對象可以是帶符號的,也可以是無符號的。如果運算對象是帶符號的且它的值爲負,那麼位運算符如何處理運算對象的“符號位”依賴於機器。而且,此時的左移操作可能會改變符號位的值,因此是一種未定義的行爲。

建議:僅將位運算符用於處理無符號類型。

例子

unsigned char bits=0233;
//移位運算符
bits=0233;bits<<8;cout<<bits<<endl;
bits=0233;bits<<31;cout<<bits<<endl;
bits=0233;bits>>3;cout<<bits<<endl;
//位求反運算符
bits=0227;~bits;cout<<bits<<endl;

0233是八進制的字面值,將其轉爲十進制數得:2×82+3×81+3×80=128+24+3=1552 \times8^2+3 \times8^1+3 \times8^0=128+24+3=155,再將其轉爲二進制數得:2->010,3->011,3->011,0233->10011011

0227是八進制的字面值,將其轉爲十進制數得:2×82+2×81+7×80=128+16+7=1512 \times8^2+2 \times8^1+7 \times8^0=128+16+7=151,再將其轉爲二進制數得:2->010,2->010,7->111,0227->10010111

定義一個無符號字符類型的變量,其佔8位大小的內存:

unsigned char bits=0233;

移位運算符

在對bits進行移位操作前,首先把無符號字符類型的bits提升成int類型,然後再向左或向右移動指定位數。

bits<<8;

向左移動8位:

10011011(提升成int類型)
00000000 00000000 00000000 10011011(向左移動8位)
00000000 00000000 10011011 00000000

bits<<31;

向左移動31位,把最左邊超出邊界的7位丟棄掉:

10011011(提升成int類型)
00000000 00000000 00000000 10011011(向左移動31位)
10000000 00000000 00000000 00000000

bits>>3;

向右移動3位,把最右邊超出邊界的3位丟棄掉:

10011011(提升成int類型)
00000000 00000000 00000000 10011011(向右移動3位)
00000000 00000000 00000000 00010011

位求反運算符

char類型的運算對象首先提升成int類型,提升時運算對象原來的位保持不變,往高位(high order position)添加0即可。

~bits;

將bits提升成int類型,增加24個高位0,隨後將提升後的值逐位求反:

10010111(提升成int類型)
00000000 00000000 00000000 10011011(逐位求反)
11111111 11111111 11111111 01100100

sizeof運算符

逗號運算符

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章