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 さんは、上記の編集が間違っていると指摘しました。