算術運算符(左結合律)
運算符 | 功能 | 用法 | 例子 |
---|---|---|---|
+ | 一元正號 | + 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->010,3->011,3->011,0233->10011011
0227是八進制的字面值,將其轉爲十進制數得:,再將其轉爲二進制數得: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運算符
逗號運算符