09 演算子

05章で学んだ算術演算子に加え、複合代入・インクリメント/デクリメント・比較・論理演算子を学ぶ。
これらは if 文や繰り返しの条件式で必ず使う。


09-1 算術演算子(復習)

演算子意味結果
+加算3 + 25
-減算3 - 21
*乗算3 * 26
/除算7 / 23(整数同士は切り捨て)
%剰余7 % 21(余り)
% は整数型同士にしか使えない。floatdouble に使うとコンパイルエラーになる。

09-2 複合代入演算子

「演算した結果を同じ変数に入れる」操作を短く書ける記法。

演算子意味展開した形
x += 33を加えるx = x + 3
x -= 33を引くx = x - 3
x *= 33を掛けるx = x * 3
x /= 33で割るx = x / 3
x %= 33で割った余りにするx = x % 3
09_01_compound.c
#include <stdio.h>

int main(void)
{
    int a = 5;
    int b = 10;
    int c = 3;
    int d = 20;
    int e = 13;

    a += 3;
    printf("a += 3  → a = %d¥n", a);   /* 8 */

    b -= 4;
    printf("b -= 4  → b = %d¥n", b);   /* 6 */

    c *= 4;
    printf("c *= 4  → c = %d¥n", c);   /* 12 */

    d /= 5;
    printf("d /= 5  → d = %d¥n", d);   /* 4 */

    e %= 5;
    printf("e %%= 5  → e = %d¥n", e);  /* 3 */

    return 0;
}
a += 3  → a = 8
b -= 4  → b = 6
c *= 4  → c = 12
d /= 5  → d = 4
e %= 5  → e = 3

09-3 インクリメント・デクリメント

変数の値を1だけ増やす・減らす専用の演算子。
繰り返し処理のカウンタとして頻繁に使う。

書き方名称動作
++x前置インクリメントx を 1 増やしてから式の値として使う
x++後置インクリメント式の値として使ってから x を 1 増やす
--x前置デクリメントx を 1 減らしてから式の値として使う
x--後置デクリメント式の値として使ってから x を 1 減らす
⚠ 前置と後置の違いが出るのは「別の変数への代入と同時に使うとき」だけ。
単独で x++; と書く場合は前置・後置どちらも結果は同じ。
09_02_increment.c
#include <stdio.h>

int main(void)
{
    int x, y;

    /* 前置インクリメント:増やしてから代入 */
    x = 5;
    y = ++x;
    printf("前置 ++x : x = %d, y = %d¥n", x, y);   /* x=6, y=6 */

    /* 後置インクリメント:代入してから増やす */
    x = 5;
    y = x++;
    printf("後置 x++ : x = %d, y = %d¥n", x, y);   /* x=6, y=5 */

    /* 前置デクリメント */
    x = 5;
    y = --x;
    printf("前置 --x : x = %d, y = %d¥n", x, y);   /* x=4, y=4 */

    /* 後置デクリメント */
    x = 5;
    y = x--;
    printf("後置 x-- : x = %d, y = %d¥n", x, y);   /* x=4, y=5 */

    return 0;
}
前置 ++x : x = 6, y = 6
後置 x++ : x = 6, y = 5
前置 --x : x = 4, y = 4
後置 x-- : x = 4, y = 5
✅ 単独で使う場合(x++; だけの行)は前置・後置のどちらでも結果は同じ。
迷ったときは後置(x++)を使うのが慣習的。

09-4 演算子の優先順位

複数の演算子が混在するとき、計算される順序に規則がある。
よく使う演算子の優先順位を高い順に示す。

優先度演算子説明
()カッコ
++ --(前置)!単項演算子
|* / %乗算・除算・剰余
|+ -加算・減算
|< <= > >=大小比較
|== !=等値比較
|&&論理 AND
|||論理 OR
= += -= *= /=代入
✅ 全部を覚える必要はない。迷ったらカッコを付けて意図を明示するのが最善。

09-5 sizeof 演算子

sizeof は、型や変数が何バイトのメモリを使っているかを調べる演算子。
関数のように見えるが演算子であり、コンパイル時に値が決まる。

sizeof(型名)
sizeof(変数名)
09_05_sizeof.c
#include <stdio.h>

int main(void)
{
    int x = 100;

    /* 型のサイズを調べる */
    printf("char       : %d バイト¥n", (int)sizeof(char));
    printf("short      : %d バイト¥n", (int)sizeof(short));
    printf("int        : %d バイト¥n", (int)sizeof(int));
    printf("long       : %d バイト¥n", (int)sizeof(long));
    printf("long long  : %d バイト¥n", (int)sizeof(long long));
    printf("float      : %d バイト¥n", (int)sizeof(float));
    printf("double     : %d バイト¥n", (int)sizeof(double));

    /* 変数のサイズを調べる */
    printf("¥n変数 x のサイズ : %d バイト¥n", (int)sizeof(x));

    return 0;
}

実行結果(Visual Studio / Windows 環境):

char       : 1 バイト
short      : 2 バイト
int        : 4 バイト
long       : 4 バイト
long long  : 8 バイト
float      : 4 バイト
double     : 8 バイト

変数 x のサイズ : 4 バイト
sizeof の戻り値は size_t 型(環境によって異なる符号なし整数型)。
printf で表示するときは (int) でキャストして %d を使うか、%zu を使うとよい。
✅ 04章の「型のサイズ一覧」は知識として覚えるものだが、sizeof を使えばプログラム上で実際に確認できる。
環境によってサイズが変わる型(long など)の確認に特に有用。

09-6 比較演算子

2つの値を比較して、結果を 真(1) または 偽(0) で返す。
if 文や while 文の条件式で必ず使う。

演算子意味結果(x=5 のとき)
==等しいx == 51(真)
!=等しくないx != 01(真)
>より大きいx > 31(真)
<より小さいx < 30(偽)
>=以上x >= 51(真)
<=以下x <= 40(偽)
=(代入)と ==(比較)を混同しないこと。
条件式に = を書いても文法エラーにならず、意図しない動作になる頻出バグ。

C言語では 0 が偽、0 以外がすべて真 として扱われる。
比較の結果が「真」なら 1、「偽」なら 0 という整数値が返る。

09_03_compare.c
#include <stdio.h>

int main(void)
{
    int x = 5;

    printf("x == 5 : %d¥n", x == 5);   /* 1(真) */
    printf("x != 5 : %d¥n", x != 5);   /* 0(偽) */
    printf("x >  3 : %d¥n", x >  3);   /* 1(真) */
    printf("x <  3 : %d¥n", x <  3);   /* 0(偽) */
    printf("x >= 5 : %d¥n", x >= 5);   /* 1(真) */
    printf("x <= 4 : %d¥n", x <= 4);   /* 0(偽) */

    return 0;
}
x == 5 : 1
x != 5 : 0
x >  3 : 1
x <  3 : 0
x >= 5 : 1
x <= 4 : 0

09-7 論理演算子

複数の条件を組み合わせるときに使う。

演算子意味真になる条件
&&AND(かつ)両方が真のときx > 0 && x < 10
||OR(または)どちらかが真のときx < 0 || x > 100
!NOT(否定)元の条件が偽のとき!(x == 0)
09_04_logical.c
#include <stdio.h>

int main(void)
{
    int x = 5;

    /* AND:両方の条件が成立するか */
    printf("x>0 && x<10 : %d¥n", x > 0 && x < 10);   /* 1(真) */
    printf("x>0 && x>10 : %d¥n", x > 0 && x > 10);   /* 0(偽) */

    /* OR:どちらかの条件が成立するか */
    printf("x<0 || x>3  : %d¥n", x < 0 || x > 3);    /* 1(真) */
    printf("x<0 || x>10 : %d¥n", x < 0 || x > 10);   /* 0(偽) */

    /* NOT:条件を反転する */
    printf("!(x==5)      : %d¥n", !(x == 5));           /* 0(偽) */
    printf("!(x==0)      : %d¥n", !(x == 0));           /* 1(真) */

    return 0;
}
x>0 && x<10 : 1
x>0 && x>10 : 0
x<0 || x>3  : 1
x<0 || x>10 : 0
!(x==5)      : 0
!(x==0)      : 1

短絡評価(ショートサーキット)

&&|| では、左辺の結果だけで全体の結果が決まる場合、右辺は評価されない

演算子左辺が偽のとき左辺が真のとき
A && BB を評価しない(全体が偽と確定)B を評価する
A || BB を評価するB を評価しない(全体が真と確定)

これを利用してゼロ除算を防ぐ安全な書き方ができる:

/* x が 0 でないことを先に確認してから割り算する */
if (x != 0 && 100 / x > 1) {
    printf("OK¥n");
}
x != 0 が偽(x が 0)なら 100 / x は評価されない。ゼロ除算が起きない安全な書き方。

09-8 演習

🔧 演習① 複合代入の結果を予測してから実行しよう

次のコードを実行する前に、各 printf の出力を予測してからプログラムを打ち込んで確認しよう。

09_06_predict.c
#include <stdio.h>

int main(void)
{
    int a = 10;
    a += 5;
    a *= 2;
    a -= 3;
    a /= 3;
    printf("a = %d¥n", a);   /* 予測:? */

    int b = 7;
    printf("b++ : %d¥n", b++);   /* 予測:? */
    printf("b   : %d¥n", b);     /* 予測:? */
    printf("++b : %d¥n", ++b);   /* 予測:? */
    printf("b   : %d¥n", b);     /* 予測:? */

    return 0;
}
答えを表示
a = 9
b++ : 7
b   : 8
++b : 9
b   : 9

a の計算:10→15→30→27→9(27÷3)
b++ は現在値(7)を表示してから増加 → 表示は7、その後 b=8
++b は増加してから表示 → b=9 を表示

🔧 演習② 比較・論理演算子の結果を確認しよう

次のコードで x の値を変えながら実行し、各条件の結果(1 か 0)がどう変わるか確認しよう。
まず x = 5 で実行し、次に x = 0x = 15 で試してみよう。

09_07_conditions.c
#include <stdio.h>

int main(void)
{
    int x = 5;   /* ← この値を変えて試そう */

    printf("x = %d のとき:¥n", x);
    printf("  x > 0           : %d¥n", x > 0);
    printf("  x >= 0 && x <= 10 : %d¥n", x >= 0 && x <= 10);
    printf("  x < 0 || x > 10  : %d¥n", x < 0 || x > 10);
    printf("  x %% 2 == 0       : %d¥n", x % 2 == 0);   /* 偶数判定 */

    return 0;
}
x = 0・x = 15 のときの結果

x = 0

x = 0 のとき:
  x > 0           : 0
  x >= 0 && x <= 10 : 1
  x < 0 || x > 10  : 0
  x % 2 == 0       : 1

x = 15

x = 15 のとき:
  x > 0           : 1
  x >= 0 && x <= 10 : 0
  x < 0 || x > 10  : 1
  x % 2 == 0       : 0

09-9 理解度チェック

Q1. a *= 2 を展開した形として正しいものはどれか。

解説を表示

正解:イ

複合代入 a *= 2a = a * 2 と同じ。

Q2. 次のコードの出力として正しいものはどれか。

int x = 5;
int y = x++;
printf("%d %d¥n", x, y);
解説を表示

正解:ウ

後置インクリメントなので、まず y に x の現在値(5)を代入してから x を 1 増やす。
結果:x=6、y=5。

Q3. x = 8 のとき、x >= 5 && x <= 10 の結果はどれか。

解説を表示

正解:イ

x >= 5 は真(1)、x <= 10 も真(1)。AND なので両方真 → 結果は 1。

Q4. 短絡評価について正しい説明はどれか。

解説を表示

正解:イ

&& は左辺が偽の時点で全体が偽と確定するため、右辺を評価しない。
この性質を使って「ゼロでないか確認してから除算する」などの安全な書き方ができる。


09-10 まとめ

演算子の種類主な演算子ポイント
複合代入+= -= *= /= %=x += 3x = x + 3 の短縮形
インクリメント/デクリメント++ --前置は増減してから使用、後置は使用してから増減
比較== != > < >= <=結果は真(1)か偽(0)。=== の混同に注意
論理&& || !条件の組み合わせ。短絡評価を活用できる