2

2 つのポインターがあるとします。

char* p1 = nullptr;
char* p2 = std::malloc( 4 );
std::size_t offset = p2 - p1;

この方法でオフセットを取得しても安全ですか? これまでのところ、私のコンピューターでは問題なく動作しています。しかし、このメソッドが失敗するように、オフセットが size_t の最大数を超えることができるかどうか疑問に思っていますか?

4

3 に答える 3

6

これは未定義の動作であり、ドラフトの 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 ) ;
于 2014-07-22T14:26:35.957 に答える
3

Wojtek による回答に加えて、ポインター演算は関連するポインター間でのみ行うことができ、また行う必要があります。たとえば、 eg がある場合、2 つのポインターの差を取得するchar* p3 = p2 + 4ことができます。これは有効です。p3 - p2

ただし、次のようなもの

char* p4 = new char[4];
std::cout << p4 - p2 << '\n';

と は関連していないため、合法ではp2ありp4ません。

于 2014-07-22T14:26:25.020 に答える
3

いいえ、安全ではありません。基本的に、null ポインターでできる唯一のことは、それを別のポインターと比較することです。加算と減算に関しては、ヌル ポインターにゼロを加算または減算し、2 つのヌル ポインターを減算することしかできません。これは、汎用プログラミングで役立つ場合があります。あなたのケースは未定義の動作です。

于 2014-07-22T14:24:50.413 に答える