Kernighan&Ritchieによる「TheCProgrammingLanguage」から引用します。
任意のポインターを、ゼロとの等式または不等式について有意義に比較できます。ただし、同じ配列のメンバーを指していないポインターとの算術演算または比較の動作は定義されていません。 (例外が1つあります。配列の終わりを超えた最初の要素のアドレスは、ポインター演算で使用できます。)
これは、異なるポインタの同等性をチェックするために==
に頼ることができないことを意味しますか?この比較が間違った結果につながる状況は何ですか?
私の頭に浮かぶ1つの例は、コード用とデータ用に別々のアドレス空間を持つハーバードアーキテクチャです。そのアーキテクチャのコンピュータでは、コンパイラは定数データをコードメモリに格納できます。 2つのアドレス空間が分離しているため、コードメモリ内のアドレスへのポインタcouldは、同じアドレスを指すことなく、データメモリ内のポインタと数値的に等しくなります。
等式演算子はすべての有効なポインターに対して定義されており、「誤検知」を与えることができるのは、一方のポインターが配列の終わりを過ぎた1つの要素を指し、もう一方のポインターがたまたまポイントする場合です(または構造体定義)メモリ内の配列のすぐ先に格納されている別のオブジェクトに。
あなたの間違いはK&Rを規範として扱っていることだと思います。等式演算子については、C99標準(ここでは素敵なhtmlバージョン: http://port70.net/~nsz/c/c99/n1256.html )、6.5.9を参照してください。比較が未定義であるという問題は、関係演算子にのみ適用されます(6.5.8を参照)。
2つのポインターを比較すると、結果は、ポイントされたオブジェクトのアドレス空間内の相対的な位置によって異なります。オブジェクトまたは不完全な型への2つのポインターが両方とも同じオブジェクトを指している場合、または両方が同じ配列オブジェクトの最後の要素の1つ先を指している場合、それらは等しく比較されます。ポイントされたオブジェクトが同じ集約オブジェクトのメンバーである場合、後で宣言された構造体メンバーへのポインターは、構造体で前に宣言されたメンバーへのポインターよりも大きく比較され、より大きな添え字値を持つ配列要素へのポインターは、同じ配列の要素へのポインターよりも大きく比較されます。添え字の値が低くなります。同じユニオンオブジェクトのメンバーへのすべてのポインタは等しく比較されます。式Pが配列オブジェクトの要素を指し、式Qが同じ配列オブジェクトの最後の要素を指している場合、ポインター式Q + 1はPよりも大きく比較されます。それ以外の場合、動作は定義されていません。
私はこれを次のように解釈します:
short a[9];
int b[12];
short * c = a + 9;
ここでそれを言うことは有効です
c > a
c
はポインタ演算を介してa
から生じるため、
必ずしもそうとは限りません
b == c
または
c <= b
または、メモリ内の順序と配置が定義されていない異なる配列から生じるため、同様のものです。
異なる配列を指すポインターを比較するためにポインター比較を使用することはできません。
そう:
_int arr[5] = {1, 2, 3, 4, 5};
_
_int * p = &arr[0];
_
_int anotherarr[] = {1, 2};
_
_int * pf = &anotherarr[0];
_
p
とpf
は同じ配列を指していないため、if (p == pf)
を実行することはできません。これにより、未定義の動作が発生します。
それらが同じ配列内を指している場合は、ポインターの比較に依存できます。
私自身、算術の場合についてはよくわかりません。