問題の歴史: C言語では、ポインタは他のオブジェクトのアドレスを保持する変数です。この値を比較する方法に問題が生じました。なぜなら、メモリが予測不可能な方法で割り当てられる場合があるからです。言語はポインタ間の比較を許可しますが、その動作が明確であるためにいくつかの制約を課します。
問題: 正当な比較が可能なのは、同じ配列の要素か同じオブジェクトを指すポインタのみです。無関係なオブジェクト(異なる変数や共有配列に含まれない確保されたメモリ領域)を指すポインタの比較は未定義の動作になります。
解決策: 無関係なメモリ領域間のポインタを比較しないようにし、同じ配列/文字列/バッファ内でのみ使用し、NULLとの比較は常に安全です。
コードの例:
#include <stdio.h> int main() { int arr[5] = {1, 2, 3, 4, 5}; int *p1 = &arr[1]; int *p2 = &arr[3]; if (p1 < p2) { printf("p1はp2よりも配列の早い要素を指しています "); } }
重要な特徴:
1. mallocを通じて取得されたポインタを、異なるメモリブロックに対して比較することは可能ですか?
いいえ、そのようなポインタを比較することはできません — 標準での動作が定義されていません。同じメモリブロックを指すポインタだけで比較することが許可されており、NULLとの比較は可能です。
2. int型とdouble型のポインタを比較する場合、異なる変数を指しているが数値が同じ場合、何が返されますか?
比較は、両方のポインタが同じ型にキャストされ、同じオブジェクトを指す場合にのみ可能です。そうでない場合、結果は未定義です — アドレスの値が同じである可能性もありますが、標準はその動作を保証しません。
3. 配列の最初の要素へのポインタを、その末尾へのポインタ(例えば、arrとarr + N)と比較することは正当ですか?
はい、これは正当です。arr + Nは最後の要素の次の想像上の要素を指しており、コンパイラはarr <= arr + Nを保証します。
社員が異なるメモリの塊から割り当てられた2つの構造体の「どちらが先に作成されたか」を判断するためのアドレス比較関数を実装することに決めました。
利点:
欠点:
レビューの後、全ての構造体を共通のバッファに割り当て、許可された範囲内で比較するためのポインタの関属チェックが実装されました。
利点:
欠点: