[C言語のはじめ方] Part5: 演算子(算術、論理、比較)

C言語

プログラミングの世界へようこそ! 👋 C言語の学習を進める中で、今回は「演算子(えんざんし)」という、プログラムに計算や比較を行わせるための重要な記号について学びます。

皆さんは、算数や数学で足し算(+)や引き算(-)などの記号を使って計算してきましたよね。C言語の演算子もそれと似ています。数値の計算はもちろん、値の大小を比べたり、複数の条件を組み合わせたりと、プログラムが様々な判断や処理を行うために不可欠な要素です。

このステップでは、特に使用頻度の高い以下の3種類の演算子をマスターしていきましょう!

  • 算術演算子:足し算、引き算、掛け算、割り算など、数値計算の基本!
  • 比較演算子:2つの値の大きさや等しさを比較! 条件分岐の基礎!
  • 論理演算子:複数の条件を組み合わせて、より複雑な判断を実現!

これらの演算子を使いこなせるようになると、プログラムでできることの幅がぐっと広がります。それでは、一つずつ丁寧に見ていきましょう!🚀

1. 算術演算子:計算はおまかせ!

基本的な四則演算(+, -, *, /)

まずは、最も基本的な算術演算子である四則演算(加算、減算、乗算、除算)を見ていきましょう。これらは、私たちが普段使っている計算記号とほぼ同じです。

  • + (加算): 2つの数値を足します。
  • - (減算): 左の数値から右の数値を引きます。
  • * (乗算): 2つの数値を掛けます。(記号が × ではなく * アスタリスクである点に注意!)
  • / (除算): 左の数値を右の数値で割ります。(記号が ÷ ではなく / スラッシュである点に注意!)

実際のコード例を見てみましょう。

#include <stdio.h>

int main(void) {
    int a = 10;
    int b = 3;
    int result;

    result = a + b; // 加算
    printf("a + b = %d\n", result); // 出力: a + b = 13

    result = a - b; // 減算
    printf("a - b = %d\n", result); // 出力: a - b = 7

    result = a * b; // 乗算
    printf("a * b = %d\n", result); // 出力: a * b = 30

    result = a / b; // 除算
    printf("a / b = %d\n", result); // 出力: a / b = 3

    return 0;
}

⚠️ 整数の割り算の注意点

上のコード例で、10 / 3 の結果が 3 になっていることに気づきましたか? C言語では、整数同士の割り算の結果は整数になります。小数点以下は切り捨てられます。もし、小数点以下も計算したい場合は、後で学ぶfloat型やdouble型といったデータ型を使う必要があります。

剰余演算子 (%)

%(パーセント)記号は、剰余(じょうよ)、つまり割り算の「余り」を求める演算子です。これも整数に対して使われます。

#include <stdio.h>

int main(void) {
    int x = 10;
    int y = 3;
    int remainder;

    remainder = x % y; // 10 を 3 で割った余り
    printf("10 %% 3 = %d\n", remainder); // 出力: 10 % 3 = 1
    // printfの中で % を表示したい場合は %% と書きます

    int num = 7;
    // 偶数か奇数かの判定によく使われます
    if (num % 2 == 0) {
        printf("%d は偶数です。\n", num);
    } else {
        printf("%d は奇数です。\n", num); // こちらが出力される
    }

    return 0;
}

剰余演算子は、ある数が特定の数の倍数かどうかを判定したり、上記のように偶数・奇数を判定したりする際によく利用されます。

インクリメント (++), デクリメント (–)

プログラミングでは、変数の値を1だけ増やしたり減らしたりする操作が非常によく登場します。そのための便利な演算子がインクリメント演算子 ++ とデクリメント演算子 -- です。

  • ++ (インクリメント): 変数の値を1増やします。
  • -- (デクリメント): 変数の値を1減らします。

これらの演算子は、変数の前(前置)にも後ろ(後置)にも置くことができ、少し動作が異なります。

#include <stdio.h>

int main(void) {
    int count = 5;

    // インクリメント
    count++; // count = count + 1; と同じ意味
    printf("count++: %d\n", count); // 出力: count++: 6

    ++count; // count = count + 1; と同じ意味
    printf("++count: %d\n", count); // 出力: ++count: 7

    // デクリメント
    count--; // count = count - 1; と同じ意味
    printf("count--: %d\n", count); // 出力: count--: 6

    --count; // count = count - 1; と同じ意味
    printf("--count: %d\n", count); // 出力: --count: 5

    // 前置と後置の違い
    int x = 5;
    int y;

    y = ++x; // 前置: xをインクリメントしてからyに代入
    printf("y = ++x; -> x=%d, y=%d\n", x, y); // 出力: y = ++x; -> x=6, y=6

    x = 5; // xをリセット
    y = x++; // 後置: xの値をyに代入してからxをインクリメント
    printf("y = x++; -> x=%d, y=%d\n", x, y); // 出力: y = x++; -> x=6, y=5

    return 0;
}

💡 前置と後置の違い

他の計算式の中で使う場合、前置(++変数, --変数)と後置(変数++, 変数--)では動作が異なります。
  • 前置: まず変数の値を1増減させてから、その結果を式の評価に使います。
  • 後置: まず変数の現在の値を式の評価に使ってから、その後で変数の値を1増減させます。
最初は少し混乱するかもしれませんが、慣れてくると非常に便利です。単独で使う場合は、前置でも後置でも結果は同じです(変数の値が1増減する)。

代入演算子 (=, +=, -=, *=, /=, %=)

変数に値を格納するために、すでに =(代入演算子)を使ってきましたね。C言語には、計算と代入を同時に行うための複合代入演算子もあります。

  • = : 右辺の値を左辺の変数に代入する。
  • += : 左辺の変数に右辺の値を加算し、その結果を左辺の変数に代入する (a += ba = a + b と同じ)。
  • -= : 左辺の変数から右辺の値を減算し、その結果を左辺の変数に代入する (a -= ba = a - b と同じ)。
  • *= : 左辺の変数に右辺の値を乗算し、その結果を左辺の変数に代入する (a *= ba = a * b と同じ)。
  • /= : 左辺の変数を右辺の値で除算し、その結果を左辺の変数に代入する (a /= ba = a / b と同じ)。
  • %= : 左辺の変数を右辺の値で割った余りを求め、その結果を左辺の変数に代入する (a %= ba = a % b と同じ)。

コードが短く、読みやすくなるメリットがあります。

#include <stdio.h>

int main(void) {
    int score = 100;

    score += 10; // score = score + 10;
    printf("score += 10: %d\n", score); // 出力: score += 10: 110

    score -= 20; // score = score - 20;
    printf("score -= 20: %d\n", score); // 出力: score -= 20: 90

    score *= 2;  // score = score * 2;
    printf("score *= 2: %d\n", score);  // 出力: score *= 2: 180

    score /= 3;  // score = score / 3;
    printf("score /= 3: %d\n", score);  // 出力: score /= 3: 60 (整数除算)

    score %= 7;  // score = score % 7;
    printf("score %%= 7: %d\n", score); // 出力: score %= 7: 4 (60を7で割った余り)

    return 0;
}

2. 比較演算子:どっちが大きい?同じ?

値を比べるための記号

比較演算子は、2つの値の関係(大きい、小さい、等しいなど)を比較するための演算子です。比較の結果は、「真(しん)」か「偽(ぎ)」のどちらかになります。

C言語では、

  • 真 (true): 0 以外の数値(一般的には 1 が使われます)
  • 偽 (false): 0

として扱われます。この真偽の結果は、後で学ぶ if 文などの条件分岐で非常に重要になります。

主な比較演算子を見ていきましょう。

  • == : 等しい (左右の値が等しい場合に真) ⚠️ 代入の = と間違えないように!
  • != : 等しくない (左右の値が等しくない場合に真)
  • > : より大きい (左の値が右の値より大きい場合に真)
  • < : より小さい (左の値が右の値より小さい場合に真)
  • >= : 以上 (左の値が右の値以上の場合に真)
  • <= : 以下 (左の値が右の値以下の場合に真)
#include <stdio.h>

int main(void) {
    int x = 10;
    int y = 5;
    int z = 10;

    printf("x == y: %d\n", x == y); // 出力: x == y: 0 (偽)
    printf("x == z: %d\n", x == z); // 出力: x == z: 1 (真)

    printf("x != y: %d\n", x != y); // 出力: x != y: 1 (真)
    printf("x != z: %d\n", x != z); // 出力: x != z: 0 (偽)

    printf("x > y: %d\n", x > y);   // 出力: x > y: 1 (真)
    printf("x < y: %d\n", x < y);   // 出力: x < y: 0 (偽)

    printf("x >= z: %d\n", x >= z); // 出力: x >= z: 1 (真)
    printf("x <= y: %d\n", x <= y); // 出力: x <= y: 0 (偽)

    // 条件式の結果を直接 if 文で使う例
    if (x > y) {
        printf("x は y より大きいです。\n"); // このメッセージが出力される
    }

    return 0;
}

🚨 超重要:=== の違い

プログラミング初心者が非常によく間違えるのが、代入の = と比較の == の混同です。
  • a = 5; は、変数 a5代入する命令です。
  • a == 5; は、変数 a の値が 5等しいかどうかを比較する式です(結果は真か偽)。
特に if 文の中で if (a = 5) と書いてしまうと、これは「aに5を代入し、その結果(5)は真なので、常にif文の中が実行される」という意味になり、意図しない動作を引き起こします。十分注意してください!

3. 論理演算子:条件を組み合わせる!

AND, OR, NOT

論理演算子は、複数の比較演算の結果(真偽)を組み合わせて、より複雑な条件を作るために使われます。「A かつ B」や「A または B」、「A ではない」といった条件を表現できます。

  • && (論理 AND): 左右の条件が両方とも真の場合に、全体として真になります。
  • || (論理 OR): 左右の条件のどちらか一方、または両方が真の場合に、全体として真になります。
  • ! (論理 NOT): 条件の真偽を反転させます。真なら偽に、偽なら真になります。(これは一つの条件に対して使います)

具体的な使い方を見てみましょう。

#include <stdio.h>

int main(void) {
    int age = 25;
    int has_license = 1; // 1は真 (免許を持っている)
    int is_student = 0; // 0は偽 (学生ではない)

    // 条件1: 20歳以上 かつ 免許を持っているか?
    if (age >= 20 && has_license == 1) {
        printf("成人で免許を持っています。\n"); // こちらが出力される
    } else {
        printf("成人ではないか、免許を持っていません。\n");
    }

    // 条件2: 18歳未満 または 学生か?
    if (age < 18 || is_student == 1) {
        printf("未成年または学生です。\n");
    } else {
        printf("成人で学生ではありません。\n"); // こちらが出力される
    }

    // 条件3: 免許を持っていないか? (!演算子で反転)
    if (!has_license) { // has_license == 0 と同じ意味
        printf("免許を持っていません。\n");
    } else {
        printf("免許を持っています。\n"); // こちらが出力される
    }

    // 複雑な組み合わせ
    // 20歳以上65歳未満で、かつ、(免許を持っている または 学生である) か?
    if (age >= 20 && age < 65 && (has_license == 1 || is_student == 1)) {
        printf("活動的な年齢層で、免許を持っているか学生です。\n"); // こちらが出力される
    }

    return 0;
}

短絡評価 (Short-circuit evaluation)

論理演算子 &&|| には、「短絡評価」という少し特殊な性質があります。これは、式全体の真偽が確定した時点で、それ以降の評価を行わないというものです。

  • A && B: もし A が偽 (0) なら、B が真か偽かに関わらず全体の結果は偽になることが確定します。そのため、B の式は評価(実行)されません。
  • A || B: もし A が真 (0以外) なら、B が真か偽かに関わらず全体の結果は真になることが確定します。そのため、B の式は評価(実行)されません。

これは、プログラムの効率を少し良くしたり、特定の条件下でのみ実行したい処理を記述したりする際に役立つことがあります。今の段階では「そういうものがあるんだな」程度に覚えておけば大丈夫です。

4. 演算子の優先順位と結合規則

一つの式の中に複数の演算子が含まれている場合、どの演算から先に計算されるのでしょうか? そのルールが「優先順位」と「結合規則」です。

優先順位:

算数と同じように、C言語の演算子にも優先順位があります。例えば、掛け算・割り算は、足し算・引き算よりも先に計算されます。

大まかな優先順位(高い順)は以下のようになります(今回学んだ範囲)。

  1. ++, -- (後置)
  2. ++, -- (前置), ! (論理NOT), - (単項マイナス)
  3. *, /, % (乗算、除算、剰余)
  4. +, - (加算、減算)
  5. <, <=, >, >= (比較)
  6. ==, != (等価比較)
  7. && (論理AND)
  8. || (論理OR)
  9. =, +=, -= など (代入演算子)

より詳しい優先順位表は、多くのC言語リファレンスサイトで確認できます。

結合規則:

優先順位が同じ演算子が並んでいる場合、どちらから計算するかを決めるのが結合規則です。ほとんどの演算子は左から右へ評価されます(例: a - b + c(a - b) + c と同じ)。ただし、代入演算子や単項演算子(++前置など)は右から左へ評価されます。

括弧 () の活用:

優先順位を覚えるのは大変ですし、複雑な式は間違いやすくなります。そこで役立つのが括弧 () です。括弧で囲まれた部分は、他の演算よりも優先して計算されます。

#include <stdio.h>

int main(void) {
    int result1 = 10 + 5 * 2; // 乗算が優先される
    printf("10 + 5 * 2 = %d\n", result1); // 出力: 10 + 5 * 2 = 20

    int result2 = (10 + 5) * 2; // 括弧内が優先される
    printf("(10 + 5) * 2 = %d\n", result2); // 出力: (10 + 5) * 2 = 30

    return 0;
}

推奨: 複雑な式や、優先順位が曖昧に感じられる場合は、積極的に括弧を使って計算順序を明示するようにしましょう。これにより、コードが読みやすくなり、意図しないバグを防ぐことができます。😊

まとめ

今回は、C言語のプログラムで計算や比較を行うための「演算子」について学びました。

  • 算術演算子 (+, -, *, /, %, ++, --): 数値の計算を担当します。整数除算やインクリメント/デクリメントの動作に注意しましょう。
  • 比較演算子 (==, !=, >, <, >=, <=): 値を比較し、真(1)または偽(0)の結果を返します。if文などの条件分岐で使われます。===の違いは重要です!
  • 論理演算子 (&&, ||, !): 複数の条件を組み合わせたり、条件の真偽を反転させたりします。
  • 優先順位と括弧: 演算には計算される順序があります。複雑な場合は括弧 () を使って、意図した通りの計算順序になるようにしましょう。

演算子は、プログラムの流れを制御したり、データを処理したりするための基本的な道具です。これらの演算子を理解し、使いこなすことで、より複雑で実用的なプログラムを作成できるようになります。

次のステップでは、これらの演算子(特に比較演算子と論理演算子)を活用して、プログラムの実行の流れを条件によって変える「制御構文(if文やfor文など)」について学んでいきます。お楽しみに!🎉

コメント

タイトルとURLをコピーしました