質問: ちょっと疑問に思っただけなので実際的な問題を抱えているわけではないのですが、 ポインタとメモリブロックが与えられた時にそのポインタがメモリブロック内を指しているかどうかを調べるプログラム的方法はありますか? 例えば、 文字列(つまりポインタ)とポインタが与えられた時にポインタが与えられた文字列内を指しているか? とか mallocで確保したメモリ内を与えられたポインタが指しているか? というようなことを調べる関数を書きたいということです。 例として次のような擬似コードで ``` bool 適合チェック(Type *メモリの最初, Type *メモリの最後, Type *調べたいポインタ){ return メモリの最初 <= 調べたいポインタ && 調べたいポインタ <= メモリの最後; } ``` (あるいは`bool 適合チェック(void *メモリの最初, size_t メモリのサイズ, void *調べたいポインタ)`のようなインターフェース) みたいな感じで書きたいように思いますが、 (おそらく多くの場面で期待するように動作するだろうと思われますが) Cの規格上ポインタが有効なメモリブロック(と+1の)範囲内であれば 比較したり減算したりということは有効ですが、 範囲外であれば、動作未定義となるのでこのようには書くことはできません。 では、実質的にCの規格に沿う形でこのような関数を記述することは出来ないのでしょうか? できるとすればどのように記述すればいいですか? ※要素の型またはサイズが分かっている場合にはループして`==`で有効ポインタを全数チェックすることで可能かもしれませんがそれは避けたいです。
回答: [c](/questions/tagged/c "'c' のタグが付いた質問を表示") 言語規格書 ISO/IEC 9899 [c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") 言語規格書 ISO/IEC 14882 に通じていない人のために話の整理から ISO/IEC 14882:1998 5.7 加減演算子 および ISO/IEC 9899:1999 6.5.6 加減演算子 `P` が配列オブジェクトの最後の要素を指すとき `(P)+1` は最後の要素を1つ越えたところを指す `Q` が配列オブジェクトの最後の要素を1つ越えたところを指すとき `(Q)-1` は最後の要素を指す `Q` を `*` の評価の対象としてはならない ISO/IEC 14882:1998 5.9 関係演算子 その他のポインタ比較は未規定とする ISO/IEC 9899:1999 6.5.8 関係演算子 その他のすべての場合動作は未定義とする なので `T array[N];` と `T val;` があるとき、提示のサンプルに ``` if (適合チェック(array, array+N, &val)) {...} ``` としても結果は [c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") の場合未規定 [c](/questions/tagged/c "'c' のタグが付いた質問を表示") の場合未定義、ということです。 ISO/IEC 14882:1998 5.10 等価演算子 ISO/IEC 9899:1999 6.5.9 等価演算子 等価演算子に対しては「未定義」の文言が無い ということで `==` なら安全ってことで。 で、題意についてですけど・・・無い、んぢゃないっすかね? C/C++ の言語仕様書厳密合致の範囲で、なんですよね? ていうことは「いかなる処理系でもこの方法で、ソース修正なしにうまく動く必然がある」ってことで。 オーダー O(1) のコストで実現するには、処理系の実装を問わずにどうこうは難しいと思われます。 ポインタ値の範囲だけわかっても - const なオブジェクトを指すポインタに対して書き込む deref はできない - 範囲は正しくても境界整合してないポインタ値を使うことはできない とかもっと別の制約がありそうですし。 オイラなら言語規格書のレベルでの妥当性はあきらめて 「今開発対象としているこの処理系ならこのコードで良し」として妥協します。