web-dev-qa-db-ja.com

IntPtrとは正確には何ですか?

IntelliSenseを使用して他の人のコードを見ることで、このIntPtrタイプに出会いました。使用する必要があるたびに、単にnullまたはIntPtr.Zeroを入力するだけで、ほとんどの機能が動作することがわかりました。それは正確に何であり、いつ/なぜ使用されますか?

161
Callum Rogers

これは「ネイティブ(プラットフォーム固有)サイズの整数」です。内部的にはvoid*として表されますが、整数として公開されます。アンマネージポインターを保存する必要があり、unsafeコードを使用したくない場合はいつでも使用できます。 IntPtr.Zeroは実質的にNULL(ヌルポインター)です。

151
Sam Harwell

これは、ネイティブコードまたは安全でないコードで使用されるメモリアドレスを格納するのに十分な大きさの値型ですが、安全なマネージコードでメモリアドレスとして直接使用することはできません。

IntPtr.Sizeを使用して、32ビットプロセスで実行しているか64ビットプロセスで実行しているかを確認できます。それぞれ4バイトまたは8バイトです。

61

以下に例を示します。

私は、高速カメラと連動するC#プログラムを書いています。カメラには、画像を取得し、コンピューターのメモリに自動的に読み込む独自のドライバーがあります。

したがって、最新の画像をプログラムに取り込んで作業する準備ができたら、カメラドライバーはIntPtrを提供し、画像の保存先は既に物理メモリに保存されているので、時間/リソースを無駄にして別のものを作成する必要はありません既にメモリ内にある画像を保存するメモリブロック。 IntPtrは、画像が既にどこにあるかを示しています。

41
bufferz

直接解釈

IntPtrは、integerであり、これはポインター

IntPtrを使用して、ポインター値を非ポインター型に格納できます。この機能は.NETで重要です。ポインターを使用するとエラーが発生しやすく、ほとんどのコンテキストで違法となるためです。ポインター値を「安全な」データ型に格納できるようにすることで、unsafeコードセグメント間の配管をより安全な高レベルコードに実装できます。ポインターを直接サポートしない言語。

IntPtrのサイズはプラットフォーム固有ですが、システムが自動的に正しいサイズを使用するため、この詳細を考慮する必要はほとんどありません。

「IntPtr」という名前は紛らわしいです-Handleのようなものがより適切だったかもしれません。私の最初の推測では、「IntPtr」は整数へのポインターでした。 IntPtrのMSDNドキュメント は、名前の意味についての多くの洞察を提供することなく、やや不可解な詳細に入ります。

別の視点

IntPtrは、2つの制限があるポインターです。

  1. 直接間接参照することはできません
  2. それが指すデータのタイプを知りません。

言い換えれば、IntPtrvoid* のようなものですが、基本的なポインター演算に使用できる(ただし使用すべきではない)特別な機能を備えています。

IntPtrを逆参照するには、真のポインター(「安全でない」コンテキストでのみ実行できる操作)にキャストするか、InteropServices.Marshalで提供されるようなヘルパールーチンに渡すことができます。クラス。 Marshalクラスを使用すると、明示的な「安全でない」コンテキストにいる必要がないため、安全性の錯覚を与えます。ただし、ポインターの使用に固有のクラッシュのリスクは除去されません。

33
nobar

ポインターとは?

すべての言語で、ポインターはメモリアドレスを格納する変数の一種であり、それらを指すように指示することができますアドレスそれらが指しているか、またはアドレスの値彼らは指している。

ポインターは、一種のブックマークと考えることができます。ただし、本のページにすばやくジャンプするために使用される代わりに、ポインタを使用してメモリのブロックを追跡またはマップします。

プログラムのメモリが65535バイトの1つの大きな配列のように正確に想像してください。

ポインタが素直に指す

ポインタはそれぞれ1つのメモリアドレスを記憶するため、メモリ内の単一のアドレスを指します。

グループとして、ポインタはメモリアドレスを記憶および呼び出し、すべてのコマンドアドネズームに従います。

あなたは彼らの王です。

C#のポインター

具体的には、C#では、ポインターは、0〜65534のメモリアドレスを格納する整数変数です。

また、C#固有のポインターはint型であるため、署名されます。

ただし、負の番号のアドレスを使用することはできません。65534を超えるアドレスにアクセスすることもできません。使用しようとすると、System.AccessViolationExceptionがスローされます。

MyPointerと呼ばれるポインターは、次のように宣言されます。

int * MyPointer;

C#のポインターはintですが、C#のメモリアドレスは0から始まり、65534まで拡張されます。

とがったものは特別な注意を払って処理する必要があります

安全でないという言葉isはあなたを怖がらせることを意図しており、非常に正当な理由から:ポインターはとがったものであり、例えば剣、軸、ポインターなどは、特別な注意を払って処理する必要があります。

ポインターにより、プログラマーはシステムを厳密に制御できます。したがって、ミスはより深刻な結果をもたらす可能性があります。

ポインターを使用するには、プログラムのプロパティで安全でないコードを有効にし、安全でないとマークされたメソッドまたはブロックでのみポインターを使用する必要があります。

安全でないブロックの例

unsafe
{
    // Place code carefully and responsibly here.

}

ポインターの使用方法

変数またはオブジェクトが宣言またはインスタンス化されると、それらはメモリに保存されます。

  • *記号プレフィックスを使用して、ポインターを宣言します。

int *MyPointer;

  • 変数のアドレスを取得するには、&記号プレフィックスを使用します。

MyPointer = &MyVariable;

アドレスがポインターに割り当てられると、次のことが適用されます。

  • *プレフィックスなしで、intとしてポイントされるメモリアドレスを参照します。

MyPointer = &MyVariable; // Set MyPointer to point at MyVariable

  • *プレフィックスを使用して、ポイントされているメモリアドレスに格納されている値を取得します。

"MyPointer is pointing at " + *MyPointer;

ポインタはメモリアドレスを保持する変数であるため、このメモリアドレスはポインタ変数に格納できます。

慎重かつ責任を持って使用されているポインターの例

    public unsafe void PointerTest()
    {
        int x = 100; // Create a variable named x

        int *MyPointer = &x; // Store the address of variable named x into the pointer named MyPointer

        textBox1.Text = ((int)MyPointer).ToString(); // Displays the memory address stored in pointer named MyPointer

        textBox2.Text = (*MyPointer).ToString(); // Displays the value of the variable named x via the pointer named MyPointer.

    }

ポインターの型がintであることに注意してください。これは、C#がメモリアドレスを整数(int)として解釈するためです。

なぜuintではなくintですか?

正当な理由はありません。

ポインターを使用する理由

ポインターはとても楽しいです。コンピュータの多くがメモリによって制御されているため、プログラマはプログラムのメモリをより詳細に制御できます。

メモリ監視

ポインタを使用してメモリブロックを読み取り、時間の経過とともに変化するポイントの値を監視します。

これらの値を責任を持って変更し、変更がコンピューターに与える影響を追跡します。

13

MSDNによると:

IntPtr型は、サイズがプラットフォーム固有の整数になるように設計されています。つまり、このタイプのインスタンスは、32ビットのハードウェアおよびオペレーティングシステムでは32ビットであり、64ビットのハードウェアおよびオペレーティングシステムでは64ビットであると予想されます。

IntPtr型は、ポインターをサポートする言語で使用でき、ポインターをサポートする言語とサポートしない言語間でデータを参照する一般的な手段として使用できます。

IntPtrオブジェクトを使用して、ハンドルを保持することもできます。たとえば、IntPtrのインスタンスは、ファイルハンドルを保持するためにSystem.IO.FileStreamクラスで広範囲に使用されます。

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

http://msdn.Microsoft.com/en-us/library/system.intptr(VS.71).aspx

7
Zyphrax

これは MSDNページ で、IntPtrを扱います。

最初の行は次のとおりです。

ポインターまたはハンドルを表すために使用されるプラットフォーム固有のタイプ。

ポインターまたはハンドルが何であるかについては、ページは次の状態になります。

IntPtr型は、ポインターをサポートする言語で使用でき、ポインターをサポートする言語とサポートしない言語間でデータを参照する一般的な手段として使用できます。

IntPtrオブジェクトを使用して、ハンドルを保持することもできます。たとえば、IntPtrのインスタンスは、ファイルハンドルを保持するためにSystem.IO.FileStreamクラスで広範囲に使用されます。

ポインターは、関心のあるデータを保持するメモリ領域への参照です。

ハンドルはオブジェクトの識別子になることができ、両側がそのオブジェクトにアクセスする必要があるときにメソッド/クラス間で渡されます。

5
ChrisF

IntPtr は、主にメモリアドレスまたはハンドルを保持するために使用される value type です。 ポインタ はメモリアドレスです。ポインターは、タイプ(例:int*)またはタイプなし(例:void*)にできます。 Windowsハンドル は、通常はメモリアドレスと同じサイズ(またはそれより小さい)の値で、システムリソース(ファイルやウィンドウなど)を表します。

0
cdiggins