2 つのポインターがあるとします。
char* p1 = nullptr;
char* p2 = std::malloc( 4 );
std::size_t offset = p2 - p1;
この方法でオフセットを取得しても安全ですか? これまでのところ、私のコンピューターでは問題なく動作しています。しかし、このメソッドが失敗するように、オフセットが size_t の最大数を超えることができるかどうか疑問に思っていますか?
これは未定義の動作であり、ドラフトの C++ 標準セクション5.7
加法演算子:
同じ配列オブジェクトの要素への 2 つのポインターを減算すると、結果は 2 つの配列要素の添え字の差になります。結果の型は実装定義の符号付き整数型です。この型は、ヘッダー (18.2) で std::ptrdiff_t として定義されているものと同じ型でなければなりません。[...] 両方のポインターが同じ配列オブジェクトの要素、または配列オブジェクトの最後の要素の 1 つ後ろを指していない限り、動作は未定義です。82
また、参考文献に記載されているように、結果はありstd::ptrdiff_t
ませんsize_t
。
一方0
、段落7で説明されている値を加算または減算できます。
ポインター値に値 0 を加算または減算すると、結果は元のポインター値と等しくなります。2 つのポインターが同じオブジェクトを指している場合、または両方が同じ配列の末尾の 1 つ後ろを指している場合、または両方が null である場合、2 つのポインターを減算すると、結果は std::ptrdiff_t 型に変換された値 0 と等しくなります。
ポインターを整数値に変換する場合は、intptr_t または uinitptr_tを使用する必要があります。
intptr_t integer type capable of holding a pointer uintptr_t unsigned integer type capable of holding a pointer
例えば:
uintptr_t ip = reinterpret_cast<uintptr_t>( p2 ) ;
Wojtek による回答に加えて、ポインター演算は関連するポインター間でのみ行うことができ、また行う必要があります。たとえば、 eg がある場合、2 つのポインターの差を取得するchar* p3 = p2 + 4
ことができます。これは有効です。p3 - p2
ただし、次のようなもの
char* p4 = new char[4];
std::cout << p4 - p2 << '\n';
と は関連していないため、合法ではp2
ありp4
ません。
いいえ、安全ではありません。基本的に、null ポインターでできる唯一のことは、それを別のポインターと比較することです。加算と減算に関しては、ヌル ポインターにゼロを加算または減算し、2 つのヌル ポインターを減算することしかできません。これは、汎用プログラミングで役立つ場合があります。あなたのケースは未定義の動作です。