天天看點

C++基礎知識(四)—— 操作符/運算符

    前面已經學習了變量和常量,我們可以開始對它們進行操作,這就要用到C++的操作符。有些語言,很多操作符都是一些關鍵字, 比如add, equals等等。C++的操作符主要是由符号組成的。這些符号不在字母表中,但是在所有鍵盤上都可以找到。這個特點使得C++程式更簡潔,也更國際化。運算符是C++語言的基礎,是以非常重要。

    你不需要背下所有這一小節的内容,這些細節知識僅供你以後需要時參考 。

指派Assignation (=)

指派運算符的功能是将一個值賦給一個變量。

a = 5;

将整數5賦給變量a。= 運算符左邊的部分叫做lvalue (left value),右邊的部分叫做rvalue (right value)。lvalue 必須是一個變量,而右邊的部分可以是一個常量,一個變量,一個運算(operation)的結果或是前面幾項的任意組合。

有必要強調指派運算符永遠是将右邊的值賦給左邊,永遠不會反過來。

a = b;

将變量b (rvalue)的值賦給變量a (lvalue),不論a當時存儲的是什麼值。同時考慮到我們隻是将b的數值賦給a,以後如果b的值改變了并不會影響到a的值.

例如:如果我們使用以下代碼(變量值的變化顯示在綠色注釋部分):

// 指派符号例子

#include <iostream>
using namespace std;

int main ()
{
  int a, b;         // a:?,  b:?
  a = 10;           // a:10, b:?
  b = 4;            // a:10, b:4
  a = b;            // a:4,  b:4
  b = 7;            // a:4,  b:7

  cout << "a:";
  cout << a;
  cout << " b:";
  cout << b;

  return 0;
}
      
a:4 b:7                     

以上代碼結果是a的值為4, b的值為7。最後一行中b的值被改變并不會影響到a,雖然在此之前我們聲明了a = b; (從右到左規則right-to-left rule)。

C++擁有而其他語言沒有的一個特性是指派符 (=) 可以被用作另一個指派符的rvalue (或rvalue的一部分) 。例如:

a = 2 + (b = 5);

等同于:

b = 5; a = 2 + b;

它的意思是:先将5賦給變量b,然後把前面對b的指派運算的結果(即5)加上2再賦給變量a,這樣最後a中的值為7。是以,下面的表達式在C++中也是正确的:

a = b = c = 5; //将5同時賦給3個變量a, b和c。

數學運算符Arithmetic operators ( +, -, *, /, % )

C++語言支援的5種數學運算符為:

  • + 加addition
  • - 減subtraction
  • * 乘multiplication
  • / 除division
  • % 取模module

加減乘除運算想必大家都很了解,它們和一般的數學運算符沒有差別。

唯一你可能不太熟悉的是用百分号(%)表示的取模運算(module)。取模運算是取兩個整數相除的餘數。例如,如果我們寫a = 11 % 3;,變量a的值将會為結果2,因為2是11除以3的餘數。

組合運算符Compound assignation operators (+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=)

C++以書寫簡練著稱的一大特色就是這些組合運算符compound assignation operators (+=, -=, *= 和 /= 及其他) ,這些運算符使得隻用一個基本運算符就可改寫變量的值:

value += increase; 等同于 value = value + increase;

a -= 5; 等同于 a = a - 5;

a /= b; 等同于 a = a / b;

price *= units + 1; 等同于 price = price * (units + 1);

其他運算符以此類推。例如:

// 組合運算符例子

#include <iostream>
using namespace std;

int main ()
{
  int a, b=3;
  a = b;
  a+=2;             // 相當于 a=a+2
  cout << a;
  return 0;
}
      
5                        

遞增和遞減Increase and decrease

書寫簡練的另一個例子是遞增(increase)運算符 (++)和遞減(decrease) 運算符(--)。它們使得變量中存儲的值加1或減1。它們分别等同于+=1和-=1。是以:

a++; a+=1; a=a+1; 

在功能上全部等同,即全部使得變量a的值加1。

它的存在是因為最早的C編譯器将以上三種表達式的編譯成不同的機器代碼,不同的機器代碼運作速度不一樣。現在,編譯器已經基本自動實行代碼優化,是以以上三種不同的表達方式編譯成的機器代碼在實際運作上已基本相同。

這個運算符的一個特點是它既可以被用作prefix字首,也可以被用作字尾suffix,也就是說它既可以被寫在變量辨別的前面(++a),也可以被寫在後面(a++)。雖然在簡單表達式如a++或++a中,這兩種寫法代表同樣的意思,但當遞增increase或遞減decrease的運算結果被直接用在其它的運算式中時,它們就代表非常不同的意思了:當遞增運算符被用作字首prefix (++a) 時,變量a的值線增加,然後再計算整個表達式的值,是以增加後的值被用在了表達式的計算中;當它被用作字尾suffix (a++)時,變量a的值在表達式計算後才增加,是以a在增加前所存儲的值被用在了表達式的計算中。注意以下兩個例子的不同:

例 1 例 2

B=3; A=++B; // A 的值為 4, B 

的值為

 4

B=3; A=B++; // A 

的值為

 3, B 

的值為

 4

在第一個例子中,B在它的值被賦給A之前增加1。而在第二個例子中B原來的值3被賦給 A然後B的值才加1變為4。

關系運算符Relational operators ( ==, !=, >, <, >=, <= )

我們用關系運算符來比較兩個表達式。如ANSI-C++ 标準中指出的,關系預算的結果是一個bool值,根據運算結果的不同,它的值隻能是真true或false。

例如我們想通過比較兩個表達式來看它們是否相等或一個值是否比另一個的值大。以下為C++的關系運算符:

== 相等Equal
!= 不等Different
> 大于Greater than
< 小于Less than
>= 大于等于Greater or equal than
<= 小于等于Less or equal than

下面你可以看到一些實際的例子:

(7 == 5) 将傳回false.
(5 > 4) 将傳回true.
(3 != 2) 将傳回true.
(6 >= 6) 将傳回true.
(5 < 5) 将傳回false.

當然,除了使用數字常量,我們也可以使用任何有效表達式,包括變量。假設有a=2, b=3和c=6,

(a == 5) 将傳回false.
(a*b >= c) 将傳回true 因為它實際是(2*3 >= 6)
(b+4 > a*c) 将傳回false因為它實際是(3+4 > 2*6)
((b=2) == a) 将傳回true.

注意:運算符= (單個等号)不同于運算符== (雙等号)。第一個是指派運算符(将等号右邊的表達式值賦給左邊的變量);第二個(==)是一個判斷等于的關系運算符,用來判斷運算符兩邊的表達式是否相等。是以在上面例子中最後一個表達式((b=2) == a),我們首先将數值2賦給變量b,然後把它和變量a進行比較。因為變量a中存儲的也是數值2,是以整個運算的結果為true。

C++基礎知識(四)—— 操作符/運算符

在ANSI-C++标準出現之前的許多編譯器中,就像C語言中,關系運算并不傳回值為真true或假false的bool值,而是傳回一個整型數值最為結果,它的數值可以為0,代表"false"或一個非0數值(通常為1)來代表"true"。

邏輯運算符Logic operators ( !, &&, || )

運算符 ! 等同于boolean 運算NOT (取非),它隻有一個操作數(operand),寫在它的右邊。它做的唯一工作就是取該操作數的反面值,也就是說如果操作數值為真true,那麼運算後值變為假false,如果操作數值為假false,則運算結果為真true。它就好像是說取與操作數相反的值。例如:

!(5 == 5) 傳回false,因為它右邊的表達式(5 == 5)為真true.
!(6 <= 4) 傳回true因為(6 <= 4)為假false.
!true 傳回假false.
!false 傳回真true.

邏輯運算符&&和||是用來計算兩個表達式而獲得一個結果值。它們分别對應邏輯運算中的與運算AND 和或運算OR。它們的運算結果取決于兩個操作數(operand)的關系:

第一個操作數

a

第二個操作數

b

結果 

a && b

結果

a || b

true true true true
true false false true
false true false true
false false false false

例如 :

( (5 == 5) && (3 > 6) ) 傳回false ( true && false ).

( (5 == 5) || (3 > 6)) 傳回true ( true || false ).

條件運算符Conditional operator ( ? )

條件運算符計算一個表達式的值并根據表達式的計算結果為真true或假false而傳回不同值。它的格式是:

condition ? result1 : result2 (條件?傳回值1:傳回值2)

如果條件condition 為真true,整個表達式将傳回esult1,否則将傳回result2。

7==5 ? 4 : 3 傳回3,因為7不等于5.
7==5+2 ? 4 : 3 傳回4,因為7等于5+2.
5>3 ? a : b 傳回a,因為5大于3.
a>b ? a : b 傳回較大值,a 或b.
// 條件運算符例子

#include <iostream>
using namespace std;

int main ()
{
  int a,b,c;

  a=2;
  b=7;
  c = (a>b) ? a : b;

  cout << c;

  return 0;
}
      
7                        

上面的例子中a的值為2,b的值為7,是以表達式(a>b)運算值為假(false),是以整個表達式(a>b)?a:b要取分号後面的值,也就是b的值7。是以最後輸出 c 的值為7。

逗号運算符 ( , )

逗号運算符 (,) 用來分開多個表達式,并隻取最右邊的表達式的值傳回。

例如有以下代碼:

a = (b=3, b+2);

這行代碼首先将3指派給變量b,然後将  b+2  指派給變量  a 。是以最後變量 a  的值為5,而變量b的值為 3 。

位運算符Bitwise Operators ( &, |, ^, ~, <<, >> )

位運算符以比特位改寫變量存儲的數值,也就是改寫變量值的二進制表示:

op asm Description
& AND 邏輯與 Logic AND
| OR 邏輯或Logic OR
^ XOR 邏輯異或Logical exclusive OR
~ NOT 對1取補(位反轉)Complement to one (bit inversion)
<< SHL 左移Shift Left
>> SHR 右移Shift Right

變量類型轉換運算符Explicit type casting operators

變量類型轉換運算符可以将一種類型的資料轉換為另一種類型的資料。在寫C++中有幾種方法可以實作這種操作,最常用的一種,也是與C相容的一種,是在原轉換的表達式前面加用括号()括起的新資料類型:

int i; 

float f = 3.14;

i = (int) f;

以上代碼将浮點型數字3.14轉換成一個整數值(3)。這裡類型轉換操作符為(int)。在C++中實作這一操作的另一種方法是使用構造函數constructor 的形式:在要轉換的表達式前加變量類型并将表達式括在括号中:

i = int ( f );

以上兩種類型轉換的方法在C++中都是合法的。另外ANSI-C++針對面向對象程式設計(object oriented programming)增加了新的類型轉換操作符 (參考Section 5.4, Advanced class type-casting).

sizeof()

這個運算符接受一個輸入參數,該參數可以是一個變量類型或一個變量自己,傳回該變量類型(variable type) 或對象(object)所占的位元組數:

a = sizeof (char);

這将會傳回1給a,因為char是一個常為1個位元組的變量類型。

sizeof傳回的值是一個常數,是以它總是在程式執行前就被固定了。

其它運算符

在本教程後面的章節裡我們将看到更多的運算符,比如指向指針的運算或面向對象程式設計特有的運算,等等,我們會在它們各自的章節裡進行詳細讨論。

運算符的優先度 Precedence of operators

當多個操作數組成複雜的表達式時,我們可能會疑惑哪個運算先被計算,哪個後被計算。例如以下表達式:

a = 5 + 7 % 2

我們可以懷疑它實際上表示:

a = 5 + (7 % 2) 結果為6,還是 a = (5 + 7) % 2 結果為0?

正确答案為第一個,結果為6。每一個運算符有一個固定的優先級,不僅對數學運算符(我們可能在學習數學的時候已經很了解它們的優先順序了),所有在C++中出現的運算符都有優先級。從最從最進階到最低級,運算的優先級按下表排列:

優先級

Level

操作符

Operator

說明

Description

結合方向

Grouping

1 :: 範圍 從左到右
2 () [] . -> ++ -- dynamic_cast static_cast reinterpret_cast const_cast typeid 字尾 從左到右
3 ++ -- ~ ! sizeof new delete 一進制(字首) 從右到左
* & 指針和取位址
+ - 一進制符号
4 (type) 類型轉換  從右到左
5 .* ->* 指向成員的指針 從左到右
6 * / % 乘、除、取模 從左到右
7 + - 加減 從左到右
8 << >> 位移 從左到右
9 < > <= >= 關系操作符 從左到右
10 == != 等于、不等于 從左到右
11 & 按位與運算 從左到右
12 ^ 按位異或運算 從左到右
13 | 按位或運算 從左到右
14 && 邏輯與運算 從左到右
15 || 邏輯或運算 從左到右
16 ?: 條件運算 從右到左
17 = *= /= %= += -= >>= <<= &= ^= |= 指派運算 從右到左
18 , 逗号 從左到右

結合方向Grouping定義了當有同優先級的多個運算符在一起時,哪一個必須被首先運算,最右邊的還是最左邊的。

所有這些運算符的優先級順序可以通過使用括号parenthesis signs (和)來控制,而且更易讀懂,例如以下例子:

a = 5 + 7 % 2;

根據我們想要實作的計算的不同,可以寫成:

a = 5 + (7 % 2); 或者  a = (5 + 7) % 2;

是以如果你想寫一個複雜的表達式而不敢肯定各個運算的執行順序,那麼就加上括号。這樣還可以使代碼更易讀懂。

繼續閱讀