C言語プログラミング:インクリメント/デクリメント演算子を使いこなしてレベルアップ


インクリメント演算子 (++)

1 種類と書き方

インクリメント演算子には、前置インクリメント後置インクリメント の2種類があります。

  • 後置インクリメント (x++):式で使用してから、変数 x の値を 1増 します。
  • 前置インクリメント (++x):変数 x の値を 1増 してから、その値を式で使用します。

2 具体的な動作

以下の例を見てみましょう。

int x = 10;
int y = ++x; // 前置インクリメント
int z = x++; // 後置インクリメント

printf("x = %d, y = %d, z = %d\n", x, y, z);

このコードを実行すると、以下の出力が得られます。

x = 11, y = 11, z = 10
  • 後置インクリメント (x++) の場合、まず x の値を式で使用するため、10のまま z に代入されます。その後、x の値は1増やされて11になります。
  • 前置インクリメント (++x) の場合、まず x の値を1増やして11にし、その値を y に代入します。その後、x 自体の値も11になります。

つまり、前置インクリメントと後置インクリメントでは、式で使用される値と、変数の最終的な値が異なることに注意が必要です。

デクリメント演算子 (--)

1 種類と書き方

デクリメント演算子にも、前置デクリメント (--x)後置デクリメント (x--) の2種類があります。

  • 後置デクリメント (x--):式で使用してから、変数 x の値を 1減 します。
  • 前置デクリメント (--x):変数 x の値を 1減 してから、その値を式で使用します。

2 具体的な動作

int x = 10;
int y = --x; // 前置デクリメント
int z = x--; // 後置デクリメント

printf("x = %d, y = %d, z = %d\n", x, y, z);
x = 9, y = 9, z = 10
  • 後置デクリメント (x--) の場合、まず x の値を式で使用するため、10のまま z に代入されます。その後、x の値は1減らされて9になります。
  • 前置デクリメント (--x) の場合、まず x の値を1減らして9にし、その値を y に代入します。その後、x 自体の値も9になります。

こちらも、前置デクリメントと後置デクリメントでは、式で使用される値と、変数の最終的な値が異なることに注意が必要です。

  • 複雑な式で使用すると、意図しない挙動を引き起こす可能性があるため、なるべくシンプルな式で使用するようにしましょう。
  • 前置/後置の書き方によって、式で使用される値と変数の最終的な値が異なるため、意図した動作にならないよう注意が必要です。
  • インクリメント/デクリメント演算子は、主に ループのカウンタ変数 を更新したり、 条件式の評価 に利用されます。


ループカウンタの更新

for (int i = 0; i < 10; i++) {
  printf("i = %d\n", i);
}

条件式の評価

int x = 5;
if (x++ > 5) {
  printf("x は 5 より大きい\n");
} else {
  printf("x は 5 以下\n");
}

このコードは、変数 x の値が5より大きいかどうかを判定します。x++ は、条件式の評価前に x の値を1増やしているため、x が5であっても条件式は真となり、「x は 5 より大きい」と出力されます。

前述以外にも、インクリメント/デクリメント演算子は様々な場面で利用できます。

  • ビット演算
  • フラグ変数の操作
  • 配列のインデックス更新
  • 複雑な式で使用すると、可読性が低下するため、なるべくシンプルな式で使用するようにしましょう。
  • インクリメント/デクリメント演算子は、副作用を持つ演算子であるため、意図しない挙動を引き起こさないよう注意が必要です。


代替手段

  • 加算/減算演算子
    最も単純な代替手段は、加算 (+) または減算 (-) 演算子と数値リテラルを組み合わせる方法です。
int x = 10;
x = x + 1; // x を 1 増やす
x = x - 1; // x を 1 減らす

利点:

  • インクリメント/デクリメント演算子よりも汎用性が高い。
  • 読みやすく、理解しやすいコードになる。

欠点:

  • 代入演算子
    代入演算子 (=) を利用して、変数に新しい値を代入する方法です。

  • 前置インクリメント/デクリメント演算子のようなインクリメント/デクリメントを式で使用する場合、意図した動作にならない可能性がある。

  • 演算子と数値リテラルを記述する必要があるため、コードが冗長になる。

int x = 10;
x = 11; // x を 1 増やす
x = 9;  // x を 1 減らす
  • シンプルで分かりやすいコードになる。
  • ループカウンタ
    for ループの場合、カウンタ変数を直接ループ条件式の中で更新する方法があります。

  • インクリメント/デクリメントの操作であることが明示的ではない。

  • 冗長な記述になる可能性がある。

for (int i = 0; i < 10; i++) {
  printf("i = %d\n", i);
  i++; // ループごとに i を 1 増やす
}
  • ループカウンタを明示的に記述する必要がなく、コードが簡潔になる。
  • ループカウンタ以外の変数を更新する場合には利用できない。

利点・欠点の比較

方法利点欠点
加算/減算演算子読みやすく理解しやすい冗長、前置インクリメント/デクリメントの代替には不向き
代入演算子シンプル冗長、操作が明示的ではない
ループカウンタ更新簡潔ループカウンタ以外の変数更新には不向き

状況に応じた使い分け

上記のように、それぞれの代替手段にはそれぞれ利点と欠点があります。状況に応じて適切な方法を選択することが重要です。

  • ループカウンタの更新のみの場合
    ループカウンタ更新
  • コードの簡潔さを重視する場合
    代入演算子、ループカウンタ更新
  • 可読性と理解しやすさを重視する場合
    加算/減算演算子
  • 組み込み関数やライブラリ関数の中には、インクリメント/デクリメント演算子と同等の機能を提供するものがあります。
  • 複雑な式で使用する場合には、インクリメント/デクリメント演算子の方が簡潔で分かりやすいコードになる場合があります。