Durch die Verwendung von IntelliSense und das Betrachten des Codes anderer Personen bin ich auf diesen IntPtr
Typ gestoßen. Jedes Mal, wenn es verwendet werden musste, habe ich einfach null
oder IntPtr.Zero
und die meisten Funktionen zum Funktionieren gebracht. Was genau ist es und wann / warum wird es verwendet?
170
IntPtr
macht vollkommen Sinn, weil es eine ganze Zahl (wie in der mathematischen ganzen Zahl) und ein Zeiger (wie im Zeiger) ist. DerInt
Teil hat wenig mit dem Typ int zu tun - es ist ein Konzept, kein bestimmter Typ. Um fair zu sein, sagt die CLI-Spezifikation nur, dass es sich tatsächlich um eine "ganzzahlige, native Größe" handelt. NaEs ist ein Werttyp, der groß genug ist, um eine Speicheradresse zu speichern, wie sie in nativem oder unsicherem Code verwendet wird, aber nicht direkt als Speicheradresse in sicher verwaltetem Code verwendet werden kann.
Sie können verwenden
IntPtr.Size
, um herauszufinden, ob Sie in einem 32-Bit- oder 64-Bit-Prozess ausgeführt werden, da dieser 4 bzw. 8 Byte beträgt.quelle
IntPtr
auch Handles dargestellt, die unabhängig von der Architektur 32-Bit sind (Size
in diesem Fall jedoch immer noch 8). Die CLI-Spezifikation stellt nur fest, dass es sich um eine Ganzzahl handelt, die "native Größe" hat, aber nicht wirklich viel aussagt.Hier ist ein Beispiel:
Ich schreibe ein C # -Programm, das mit einer Hochgeschwindigkeitskamera verbunden ist. Die Kamera verfügt über einen eigenen Treiber, der Bilder erfasst und für mich automatisch in den Arbeitsspeicher des Computers lädt.
Wenn ich bereit bin, das neueste Bild in mein Programm zu integrieren, um damit zu arbeiten, stellt mir der Kameratreiber eine IntPtr zur Verfügung, mit der das Bild BEREITS im physischen Speicher gespeichert wird, sodass ich keine Zeit / Ressourcen für die Erstellung eines anderen verschwenden muss Speicherblock zum Speichern eines Bildes, das sich bereits im Speicher befindet. Der IntPtr zeigt mir nur, wo sich das Bild bereits befindet.
quelle
Eine direkte Interpretation
Ein IntPtr ist eine Ganzzahl , die dieselbe Größe wie ein Zeiger hat .
Mit IntPtr können Sie einen Zeigerwert in einem Nicht-Zeigertyp speichern. Diese Funktion ist in .NET wichtig, da die Verwendung von Zeigern sehr fehleranfällig und daher in den meisten Kontexten unzulässig ist. Indem der Zeigerwert in einem "sicheren" Datentyp gespeichert werden kann, kann die Installation zwischen unsicheren Codesegmenten in sichererem Code auf hoher Ebene implementiert werden - oder sogar in einer .NET-Sprache, die Zeiger nicht direkt unterstützt.
Die Größe von IntPtr ist plattformspezifisch, dieses Detail muss jedoch selten berücksichtigt werden, da das System automatisch die richtige Größe verwendet.
Der Name "IntPtr" ist verwirrend - so etwas
Handle
hätte besser passen können . Meine anfängliche Vermutung war, dass "IntPtr" ein Zeiger auf eine ganze Zahl war. Die MSDN-Dokumentation von IntPtr geht auf etwas kryptische Details ein, ohne jemals viel Einblick in die Bedeutung des Namens zu geben.Eine alternative Perspektive
An
IntPtr
ist ein Zeiger mit zwei Einschränkungen:Mit anderen Worten, a
IntPtr
ist wie avoid*
- aber mit der zusätzlichen Funktion, dass es für die grundlegende Zeigerarithmetik verwendet werden kann (aber nicht sollte).Um eine Dereferenzierung durchzuführen
IntPtr
, können Sie sie entweder in einen echten Zeiger umwandeln (eine Operation, die nur in "unsicheren" Kontexten ausgeführt werden kann) oder an eine Hilfsroutine übergeben, wie sie von derInteropServices.Marshal
Klasse bereitgestellt wird . Die Verwendung derMarshal
Klasse vermittelt die Illusion von Sicherheit, da Sie sich nicht in einem expliziten "unsicheren" Kontext befinden müssen. Es beseitigt jedoch nicht das Absturzrisiko, das mit der Verwendung von Zeigern verbunden ist.quelle
Was ist ein Zeiger?
In allen Sprachen ist ein Zeiger ein Variablentyp, in dem eine Speicheradresse gespeichert ist. Sie können ihn entweder bitten, Ihnen die Adresse mitzuteilen, auf die er zeigt, oder den Wert an der Adresse , auf die er zeigt.
Ein Zeiger kann als eine Art Lesezeichen betrachtet werden. Anstatt schnell zu einer Seite in einem Buch zu springen, wird ein Zeiger verwendet, um Speicherblöcke zu verfolgen oder zuzuordnen.
Stellen Sie sich den Speicher Ihres Programms genau wie ein großes Array von 65535 Bytes vor.
Zeiger zeigen gehorsam
Zeiger merken sich jeweils eine Speicheradresse und zeigen daher jeweils auf eine einzelne Adresse im Speicher.
Als Gruppe merken sich Zeiger Speicheradressen und rufen sie ab, wobei jeder Befehl ad nauseum befolgt wird.
Du bist ihr König.
Zeiger in C #
Zeiger sind ebenfalls spezifisch für C # und vom Typ int und daher signiert.
Sie können jedoch keine negativ nummerierten Adressen verwenden und auch nicht auf eine Adresse über 65534 zugreifen. Bei jedem Versuch wird eine System.AccessViolationException ausgelöst.
Ein Zeiger namens MyPointer wird wie folgt deklariert:
Ein Zeiger in C # ist ein int, aber die Speicheradressen in C # beginnen bei 0 und reichen bis zu 65534.
Spitze Dinge sollten mit besonderer Sorgfalt behandelt werden
Das Wort unsicher ist beabsichtigt , Sie zu erschrecken, und für einen sehr guten Grund: Pointers spitze Dinge sind, und spitze Dinge wie Schwerter, Äxte, Zeiger usw. sollte mit besonderer Sorgfalt behandelt werden.
Zeiger geben dem Programmierer eine strenge Kontrolle über ein System. Daher haben Fehler wahrscheinlich schwerwiegendere Konsequenzen.
Um Zeiger verwenden zu können, muss unsicherer Code in den Eigenschaften Ihres Programms aktiviert sein, und Zeiger müssen ausschließlich in Methoden oder Blöcken verwendet werden, die als unsicher markiert sind.
Beispiel eines unsicheren Blocks
Verwendung von Zeigern
Wenn Variablen oder Objekte deklariert oder instanziiert werden, werden sie im Speicher gespeichert.
int *MyPointer;
MyPointer = &MyVariable;
Sobald einem Zeiger eine Adresse zugewiesen wurde, gilt Folgendes:
MyPointer = &MyVariable; // Set MyPointer to point at MyVariable
"MyPointer is pointing at " + *MyPointer;
Da ein Zeiger eine Variable ist, die eine Speicheradresse enthält, kann diese Speicheradresse in einer Zeigervariablen gespeichert werden.
Beispiel für den sorgfältigen und verantwortungsvollen Umgang mit Zeigern
Beachten Sie, dass der Typ des Zeigers ein int ist. Dies liegt daran, dass C # Speicheradressen als Ganzzahlen (int) interpretiert.
Warum ist es int statt uint?
Es gibt keinen guten Grund.
Warum Zeiger verwenden?
Zeiger machen viel Spaß. Da so viel Computer vom Speicher gesteuert wird, ermöglichen Zeiger einem Programmierer eine bessere Kontrolle über den Speicher seines Programms.
Speicherüberwachung.
Verwenden Sie Zeiger, um Speicherblöcke zu lesen und zu überwachen, wie sich die Werte, auf die gezeigt wird, im Laufe der Zeit ändern.
Ändern Sie diese Werte verantwortungsbewusst und verfolgen Sie, wie sich Ihre Änderungen auf Ihren Computer auswirken.
quelle
65534
scheint als Zeigerbereich sehr falsch zu sein. Sie sollten eine Referenz angeben.System.IntPtr
. Ich würde gerne sehen, dass die Antwort am Ende aktualisiert wird und erklärt, was auch einSystem.IntPtr
und wie es sich auf unsichere Zeiger in C # bezieht.MSDN sagt uns:
http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx
quelle
Nun, das ist die MSDN-Seite , die sich damit befasst
IntPtr
.Die erste Zeile lautet:
Was ein Zeiger oder Handle ist, heißt es auf der Seite:
Ein Zeiger ist eine Referenz auf einen Speicherbereich, der einige Daten enthält, an denen Sie interessiert sind.
Ein Handle kann eine Kennung für ein Objekt sein und wird zwischen Methoden / Klassen übergeben, wenn beide Seiten auf dieses Objekt zugreifen müssen.
quelle
Ein
IntPtr
ist ein Werttyp , der hauptsächlich zum Speichern von Speicheradressen oder Handles verwendet wird. Ein Zeiger ist eine Speicheradresse. Ein Zeiger kann typisiert (zBint*
) oder untypisiert (zBvoid*
) sein. Ein Windows-Handle ist ein Wert, der normalerweise dieselbe Größe (oder kleiner) als eine Speicheradresse hat und eine Systemressource darstellt (wie eine Datei oder ein Fenster).quelle