C言語では、後置インクリメント(i++)と前置インクリメント(++i)の操作は変数の値を1増加させますが、返される値は異なります。
例:
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])のようなループが予測できない動作をするようになりました。バグはクライアントのデバイスでのテスト段階の結果でのみ発見されました。