位元詩人 [C++] 程式設計教學:運算子 (Operator)

C++運算子
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

在程式語言中,運算子是使用符號的指令。由於運算子無法再化約成更細的指令,運算子可視為程式語言的基本指令。本文介紹 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++ 的運算子優先順序清單

實際上,程式設計師不太去記憶運算子優先順序。運算子優先順序和數學運算方式相符。可以藉由撰寫簡明的敘述來減少單一敘述內的運算子數量。真的碰到較複雜的敘述時,可以用括號 () 改變運算子優先順序。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。