ProgrammingC 開発者

C言語におけるインクリメント操作(i++)と(++i)の違いを説明してください。そのセマンティクス、どちらのバリエーションをいつ使用すべきか、複雑な式でどのように危険かについて教えてください。

Hintsage AIアシスタントで面接を突破

回答

C言語では、後置インクリメント(i++)と前置インクリメント(++i)の操作は変数の値を1増加させますが、返される値は異なります。

  • i++ (後置): まず現在の値を返し、その後に増加させます。
  • ++i (前置): まず値を増加させ、その後新しい値を返します。

例:

int i = 5; int a = i++; // a == 5, i == 6 int j = 5; int b = ++j; // b == 6, j == 6

簡単な式では違いはほとんどありませんが、複雑な式(たとえば同時に複数のインクリメントがある場合)では未定義動作が発生する可能性があります。

ひっかけ問題

int a = i++ + ++i; の式を実行した後、i = 1 の場合、変数 a の値はどうなりますか?

回答:

計算はオペランドの評価順序に依存し、標準では保証されていません。また、i が値の連続使用の間に1回以上変更されるため、未定義動作を引き起こします。こう書くべきではありません!

このようなコードの例:

int i = 1; int a = i++ + ++i; // 未定義動作!このように使用しないでください!

このテーマの詳細を知らないことによる実際のエラーの例


エピソード

大規模なプロジェクトで、配列のインデックス計算は arr[i++] = getValue(++i); として書かれていました — 開発者は古い値を保持し、新しい値を同時に取得しようとしました。異なるコンパイラでは動作が異なり、時には1つの値が別の値を上書きし、時にはプログラムがクラッシュしました。原因は、一つの式での i の不正な複数変更でした。


エピソード

組込みプロジェクトでは、カウンタの値が複雑な式の一部として増加しました: if (buffer[i++] == TERMINATOR && ++i < SIZE) ... — ハードウェアによっては異なる評価順序により、誤ったインデックスが得られ、初期化されていないデータの読み取りに繋がりました。


エピソード

他のコンパイラへのコード移植時に、オペランドの評価順序の実装の違いが原因で、while (arr[i++] && i < MAX && arr[++i])のようなループが予測できない動作をするようになりました。バグはクライアントのデバイスでのテスト段階の結果でのみ発見されました。