前言
在程式語言中,運算子是使用符號的指令。由於運算子無法再化約成更細的指令,運算子可視為程式語言的基本指令。本文介紹 C++ 的運算子。
用 assert 取代標準輸出
在本文及之後的文章中,我們會在一部分範例中用 assert 來取代標準輸出入,這是因為使用 assert 可以明顯地從程式碼中看出程式設計者的意圖,如下例:
#include <cassert>
#include <iostream>
int main(void)
{
assert(3 + 4 == 7);
return 0;
}
在這個例子中,我們可以明確地知道我們要檢查的程式碼;如果使用標準輸出,我們還得將程式編譯後輸出,然後再人工確認答案,反而比較麻煩。透過 cassert 函式庫即可使用 assert 敘述。
註:assert 敘述實際上是巨集 (macro)。
算術運算子 (Arithmetic Operators)
算術運算子用於基本的代數運算。以下是 C++ 的算術運算子:
a + b:相加a - b:相減a * b:相乘a / b:相除a % b:取餘數+a:取正數-a:取負數
以下是範例程式:
#include <cassert>
int main(void)
{
assert(+3 == 3);
assert(-3 == -3);
assert(3 + 4 == 7);
assert(3 - 4 == -1);
assert(3 * 4 == 12);
/* Integer division. */
assert(3 / 4 == 0);
assert(3 % 4 == 3);
return 0;
}
注意整數相除得整數結果,浮點數相除得浮點數結果。浮點數和整數混合運算時,會將整數提升成浮點數。
遞增 (Increment) 和遞減 (Decrement)
遞增/遞減運算是一種語法糖。相當於把 a = a + 1; 簡化成表達式的寫法。根據其情境共有以下四種:
++a:前綴遞增。先遞增再取值a++:後綴遞增。先取值再遞增--a:前綴遞減。先遞減再取值a--:後綴遞減。先取值再遞減
需注意前綴和後綴的差異。以下是範例程式:
#include <cassert>
int main(void)
{
auto n = 3;
assert(n++ == 3);
assert(n == 4);
n = 3;
assert(++n == 4);
assert(n == 4);
return 0;
}
前半的 n++ 是後綴遞增,所以先進行比較完才遞增 1。相對來說,後半的 ++n 是前綴遞增,先遞增 1 才進行比較。
二元運算子 (Bitwise Operators)
二元運算子用於二進位數運算。以下是 C++ 的二元運算子:
&:且 (bitwise and)|:或 (bitwise or)^:互斥或 (bitwise xor)~:取補數<<:左移>>:右移
以下是 bitwise and 的運算方式:
| p | q | r |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 0 | 0 |
以下是 bitwise or 的運算方式:
| p | q | r |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
以下是 bitwise xor 的運算方式:
| p | q | r |
|---|---|---|
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
以下列出實例:
#include <cassert>
int main(void)
{
auto a = 0b0101;
auto b = 0b0011;
assert((a & b) == 0b0001);
assert((a | b) == 0b0111);
assert((a ^ b) == 0b0110);
assert((a << 1) == 0b1010);
assert((a >> 1) == 0b0010);
return 0;
}
指派運算子 (Assignment Operators)
指派運算子算是一種語法糖。像是 a = a + 1; 就可以改寫成 a += 1;。以下是 C++ 的指派運算子:
=:指派,未進行其他運算+=:相加後指派-=:相減後指派*=:相乘後指派/=:相除後指派%=:取餘數後指派&=:進行 bitwise and 運算後指派|=:進行 bitwise or 運算後指派^=:進行 bitwise xor 運算後指派<<=:進行左移後指派>>=:進行右移後指派
以下是實例:
#include <cassert>
int main(void)
{
auto a = 3; a += 4;
assert(a == 7);
a = 3; a -= 4;
assert(a == -1);
a = 3; a *= 4;
assert(a == 12);
a = 3; a /= 4;
assert(a == 0);
a = 3; a %= 4;
assert(a == 3);
return 0;
}
比較運算子 (Comparison Operators)
比較運算子用來比較兩值間的相對關係。以下是 C++ 的比較運算子:
==:相等!=:相異、不相等>:大於>=:大於或等於<:小於<=:小於或等於
以下是實例:
#include <cassert>
int main(void)
{
assert(3 + 4 == 7);
assert(3 + 4 != 5);
assert(3 + 4 > 5);
assert(3 + 4 >= 5);
assert(3 + 4 < 8);
assert(3 + 4 <= 8);
return 0;
}
邏輯運算子 (Logic Operators)
邏輯運算子用於邏輯運算。以下是 C++ 的邏輯運算子:
&&:且 (logical and)||:或 (logical or)!:非 (logical not)
以下是 logic and 運算的方式:
| p | q | r |
|---|---|---|
| true | true | true |
| false | true | false |
| true | false | false |
| false | false | false |
以下是 logic or 運算的方式:
| p | q | r |
|---|---|---|
| true | true | true |
| false | true | true |
| true | false | true |
| false | false | false |
以下是 logic not 運算的方式:
| p | r |
|---|---|
| true | false |
| false | true |
以下是實例:
#include <cassert>
int main(void)
{
// AND
assert((true && true) == true);
assert((true && false) == false);
assert((false && true) == false);
assert((false && false) == false);
// OR
assert((true || true) == true);
assert((true || false) == true);
assert((false || true) == true);
assert((false || false) == false);
// NOT
assert((!true) == false);
assert((!false) == true);
return 0;
}
運算子優先順序 (Operator Precedence)
在同一行敘述內碰到多個運算子時,會以運算子優先順序來決定運算順序。這裡有一份 C++ 的運算子優先順序清單。
實際上,程式設計師不太去記憶運算子優先順序。運算子優先順序和數學運算方式相符。可以藉由撰寫簡明的敘述來減少單一敘述內的運算子數量。真的碰到較複雜的敘述時,可以用括號 ( 和 ) 改變運算子優先順序。