次のようなポインターを使用して配列にゼロを格納する for ループがあるとします。
int *vp, values[5];
for(vp = &values[5-1]; vp >= &values[0]; vp--)
*vp = 0;
book- Pointers on Cは、このループに問題があると述べています。これvp >= &values[0]
は、配列の境界の外に移動したため、比較が定義されていないためです。しかし、どのように?
このコードは、古いまたは風変わりなプロセッサ アーキテクチャが除外されたとしても安全ではありません。
コンパイラのオプティマイザは、言語に関する多くのルールを組み込みます。が配列であることがわかるとvp >= &values[0]
、values
オプティマイザは がvp
配列要素または配列を超えた要素を指していると見なすことができます。それ以外の場合、式は C 言語によって定義されないためです。
したがって、オプティマイザーに埋め込まれたルールとメカニズムは、それvp >= &values[0]
が常に真であると判断する可能性があるため、for (vp = &values[5-1]; ; vp--)
書かれたかのようにコードを生成する可能性があります。これにより、終了条件のないループが発生し、 が配列の外側*vp = 0
を指して評価されると、さらに未定義の動作が発生します。vp
ポインターが符号なし整数と同等であると仮定すると、values
アドレス 0 で開始した場合にのみ問題が存在することがわかりUINT_MAX
ます。
values
問題を視覚化するために、アドレス 0x0 から始まると仮定して、何が起こるかを順を追って説明します。
iteration 1:
vp = 0x4, *vp = 0;
iteration 2:
vp = 0x3, *vp = 0;
iteration 3:
vp = 0x2, *vp = 0;
iteration 4:
vp = 0x1, *vp = 0;
iteration 5:
vp = 0x0, *vp = 0;
iteration 6:
vp = 0xFFFFFFFF; *vp = ?? // uh oh!
したがって、vp
ポインターの最小値 (0) より小さくなることはなく、無限ループ (すべてのメモリーが書き込み可能であると仮定) またはセグメンテーション違反が発生します。
また、標準によると未定義の動作です (配列の後の 1 つの要素をアドレス指定できますが、その前ではできないため) が、実際には、現実的なシステムではこれが失敗することはありません。