__sptr、__uptr

Microsoft 固有の仕様

コンパイラが 32 ビット ポインターを 64 ビット ポインターへどのように変換するかを指定するには、32 ビット ポインター宣言で __sptr または __uptr 修飾子を使用します。 たとえば、32 ビット ポインターが 64 ビット ポインター変数に割り当てられたときや、64 ビット プラットフォーム上で 32 ビット ポインターが逆参照される場合などに変換が必要になります。

64 ビット プラットフォームをサポートする Microsoft のドキュメントでは、32 ビット ポインターの最上位ビットを符号ビットと呼んでいる場合があります。 既定では、コンパイラは符号拡張を使用して 32 ビット ポインターを 64 ビット ポインターに変換します。 つまり、64 ビット ポインターの下位 32 ビットに 32 ビット ポインターの値が設定され、上位 32 ビットに 32 ビット ポインターの符号ビットの値が設定されます。 符号ビットが 0 の場合はこの変換で正しい結果が得られますが、符号ビットが 1 の場合は正しい結果が得られません。 たとえば、32 ビット アドレス 0x7FFFFFFF はこれと同等の 64 ビットアドレス 0x000000007FFFFFFF になりますが、32 ビット アドレス 0x80000000 は誤って 0xFFFFFFFF80000000 に変換されます。

__sptr (符号付きポインター) 修飾子を指定すると、ポインター変換で 64 ビット ポインターの上位ビットが 32 ビット ポインターの符号ビットに設定されます。 __uptr (符号なしポインター) 修飾子を指定すると、上位ビットが 0 に変換されます。 次の宣言では、非修飾の 2 つのポインター、__ptr32 型で修飾された 2 つのポインター、および関数パラメーターで __sptr 修飾子と __uptr 修飾子を使用しています。

int * __sptr psp;
int * __uptr pup;
int * __ptr32 __sptr psp32;
int * __ptr32 __uptr pup32;
void MyFunction(char * __uptr __ptr32 myValue);

__sptr 修飾子と __uptr 修飾子はポインター宣言で使用します。 ポインター型修飾子の位置にこれらの修飾子を配置してください。つまり、アスタリスクの後に修飾子を記述する必要があります。 メンバーへのポインターではこれらの修飾子を使用できません。 これらの修飾子は、ポインター以外の宣言には影響を与えません。

以前のバージョンとの互換性を確保するために、コンパイラ オプション /Za (言語拡張機能の無効化) が指定されていない限り、_ptr および_ptr__sptr および __uptr と同意語です。

次の例では、__sptr 修飾子と __uptr 修飾子を使用する 32 ビット ポインターを宣言しています。各 32 ビット ポインターが 64 ビット ポインター変数に代入され、各 64 ビット ポインターの 16 進値が表示されます。 この例はネイティブの 64 ビット コンパイラでコンパイルされ、64 ビット プラットフォームで実行されます。

// sptr_uptr.cpp
// processor: x64
#include "stdio.h"

int main()
{
    void *        __ptr64 p64;
    void *        __ptr32 p32d; //default signed pointer
    void * __sptr __ptr32 p32s; //explicit signed pointer
    void * __uptr __ptr32 p32u; //explicit unsigned pointer

// Set the 32-bit pointers to a value whose sign bit is 1.
    p32d = reinterpret_cast<void *>(0x87654321);
    p32s = p32d;
    p32u = p32d;

// The printf() function automatically displays leading zeroes with each 32-bit pointer. These are unrelated
// to the __sptr and __uptr modifiers.
    printf("Display each 32-bit pointer (as an unsigned 64-bit pointer):\n");
    printf("p32d:       %p\n", p32d);
    printf("p32s:       %p\n", p32s);
    printf("p32u:       %p\n", p32u);

    printf("\nDisplay the 64-bit pointer created from each 32-bit pointer:\n");
    p64 = p32d;
    printf("p32d: p64 = %p\n", p64);
    p64 = p32s;
    printf("p32s: p64 = %p\n", p64);
    p64 = p32u;
    printf("p32u: p64 = %p\n", p64);
    return 0;
}
Display each 32-bit pointer (as an unsigned 64-bit pointer):
p32d:       0000000087654321
p32s:       0000000087654321
p32u:       0000000087654321

Display the 64-bit pointer created from each 32-bit pointer:
p32d: p64 = FFFFFFFF87654321
p32s: p64 = FFFFFFFF87654321
p32u: p64 = 0000000087654321

Microsoft 固有の仕様はここまで

関連項目

Microsoft 固有の修飾子