C言語で配列を順方向に反復処理する場合、標準的なパターンは単純です。`size_t`型のインデックスを0で初期化し、それがカウントより小さいかを確認し、インクリメントします。しかし、このロジックを逆方向の反復にミラーリングしようとすると、しばしば微妙なバグが発生します。よくある間違いは、インデックスを`count - 1`で初期化し、それが0以上であるかを確認することです。`size_t`は符号なし型であるため、条件`i >= 0`は常に真(同語反復)となり、無限ループや範囲外のメモリアクセスを引き起こす可能性があります。さらに、カウントが0の場合、式`count - 1`はその型の最大可能値(`SIZE_MAX`)にラップアラウンドし、即座にエラーを引き起こします。
`ssize_t`のような符号付き整数型に切り替えるといった代替案は機能する場合がありますが、それ自体に複雑さをもたらします。符号付き整数はCの式における暗黙の型変換中に問題を引き起こす可能性があり、また`ssize_t`はすべてのプラットフォーム(Windowsなど)で標準ではありません。さらに、32ビットシステムでは、大きなバッファに対して符号付き整数を使用すると、プロモーションや切り捨ての問題が発生する可能性があります。これらの回避策は、ロジックが正しいことを確認するために注意深い検査を必要とする過度に複雑なループヘッダーをもたらすことが多く、コードの保守を困難にし、人的ミスを誘発しやすくなります。
David Priverは、ループの初期化と条件の中で後置デクリメント演算子を使用することで、これらの落とし穴を回避する、よりクリーンで慣習的な解決策を提案しています。パターン`for (size_t i = count; i--; )`は、`i`を総カウントで初期化します。後置デクリメント`i--`はループの条件の一部として評価され、値をデクリメントしますが、デクリメント*前*の値を返します。これにより、最初の反復では`count - 1`(最後の有効なインデックス)が使用され、デクリメント前に`i`が0であったときにループが終了することが保証されます。C言語において符号なしのラップアラウンドは定義されているため、最後の反復の後に`i`が0から`SIZE_MAX`にラップしたときにループは安全に終了します。このアプローチはシンプルで読みやすく、符号付き型への変換の必要もありません。
