13

RegOpenKeyExページ上の次のコメントに気付いたときの P/Invoke 宣言を見ていました。

IntPtrに変更UIntPtr: ハンドルを使用して呼び出すとIntPtr、オーバーフローが発生します。UIntPtrこれが 32 ビットおよび 64 ビットのプラットフォームで正しく動作するようにしたい場合は、これが正しい選択です。

これは私にはあまり意味がありません:IntPtrと の両方がポインターを表すとUIntPtr想定されているため、サイズは OS のビット数 (32 ビットまたは 64 ビット) と一致する必要があります。これらは数値ではなくポインターであるため、符号付きの数値は重要ではなく、それらが指すアドレスを表すビットのみが重要です。これら2つに違いがある理由は思いつきませんが、このコメントは私を不確かにしました.

UIntPtrの代わりに使用する特定の理由はありIntPtrますか? ドキュメントによると:

IntPtr型は CLS に準拠していますが、型UIntPtrは準拠していません。IntPtr共通言語ランタイムでは型のみが使用されます。UIntPtr型は、主に型とのアーキテクチャ上の対称性を維持するために提供されますIntPtr

もちろん、これは違いがないことを意味します (誰かが値を整数に変換しようとしない限り)。pinvoke.net からの上記のコメントは間違っていますか?

編集

MarkH の回答を読んだ後、少し調べてみたところ、.NET アプリケーションはラージ アドレスを認識せず、32 ビット モードでコンパイルした場合は 2GB の仮想アドレス空間しか処理できないことがわかりました。(ハックを使用してラージ アドレス対応フラグをオンにすることもできますが、MarkH の回答では、アドレス空間が 3GB ではなく 2GB のみであると想定されているため、.NET Framework 内のチェックが問題を引き起こすことが示されています。)

これは、ポインターが持つことができるすべての正しい仮想メモリ アドレス (.NET Framework に関する限り) が 0x00000000 から 0x7FFFFFFF の間にあることを意味します。この範囲が signedintに変換されると、最上位ビットが設定されていないため、負の値はありません。これは、IntPtr と UIntPtr の使用に違いはないという私の信念を補強します。私の推論は正しいですか?

Fermat2357 さんは、上記の編集が間違っていると指摘しました。

4

3 に答える 3

10

UIntPtrとしてIntPtr内部実装されています

private unsafe void* m_value;

どちらも、アドレスを表すビットのみを管理するだけです。

オーバーフローの問題について考えることができる唯一のことは、ポインター演算を実行しようとした場合です。どちらのクラスも、オフセットの加算と減算をサポートしています。ただし、この場合も、そのような操作の後、バイナリ表現は問題ないはずです。

私の経験からはUIntPtr、ポインターを署名されていないオブジェクトと見なすため、 も好みます。しかし、これは関係がなく、私の意見です。

IntPtrあなたが使用する場合でも、あなたの場合でも、違いはないようですUIntPtr

編集:

IntPtrCLR の上に unsigned をサポートしない言語があるため、CLS に準拠しています。

于 2012-11-01T05:05:43.833 に答える
4

もちろん、これは違いがないことを意味します (誰かが値を整数に変換しようとしない限り)。

残念ながら、フレームワークはこれを正確に行おうとします (x86 用に特別にコンパイルされた場合)。IntPtr(long)コンストラクターとメソッドの両方が、値を式の anにToInt32()キャストしようとします。フレームワークのデバッグ シンボルを使用した場合に表示される実装を次に示します。intchecked

    public unsafe IntPtr(long value)
    { 
        #if WIN32
            m_value = (void *)checked((int)value);
        #else
            m_value = (void *)value; 
        #endif
    } 

もちろん、値が範囲外の場合、チェックされた式は例外をスローします。代わりUIntPtrにキャストしようとするため、同じ値でオーバーフローしません。uint

于 2012-11-01T05:43:33.020 に答える