En utilisant IntelliSense et en regardant le code des autres personnes, j'ai découvert ce type IntPtr
; chaque fois qu'il a dû être utilisé, j'ai simplement mis null
ou IntPtr.Zero
et trouvé la plupart des fonctions efficaces. De quoi s'agit-il exactement et quand/pourquoi est-il utilisé?
C'est un "entier de taille native (spécifique à la plateforme)". Il est représenté en interne sous la forme void*
mais exposé en tant qu'entier. Vous pouvez l'utiliser chaque fois que vous devez stocker un pointeur non géré et que vous ne souhaitez pas utiliser de code unsafe
. IntPtr.Zero
est effectivement NULL
(un pointeur nul).
Il s'agit d'un type de valeur suffisamment grand pour stocker une adresse de mémoire telle qu'utilisée dans un code natif ou non sécurisé, mais non directement utilisable comme adresse de mémoire dans un code géré sécurisé.
Vous pouvez utiliser IntPtr.Size
pour savoir si vous exécutez un processus 32 bits ou 64 bits, puisqu'il s'agira respectivement de 4 ou 8 octets.
Voici un exemple:
J'écris un programme C # qui s'interface avec une caméra haute vitesse. L'appareil photo possède son propre pilote qui acquiert des images et les charge automatiquement dans la mémoire de l'ordinateur.
Ainsi, lorsque je suis prêt à utiliser la dernière image de mon programme, le pilote de l'appareil photo me fournit un IntPtr indiquant où l'image est DÉJÀ stockée dans la mémoire physique. Je n'ai donc pas à perdre de temps/ressources pour en créer une autre bloc de mémoire pour stocker une image déjà en mémoire. Le IntPtr me montre juste où l'image est déjà.
IntPtr est un entier de la même taille qu'un pointeur.
Vous pouvez utiliser IntPtr pour stocker une valeur de pointeur dans un type de non-pointeur. Cette fonctionnalité est importante dans .NET car l'utilisation de pointeurs est fortement sujette aux erreurs et est donc illégale dans la plupart des contextes. En permettant à la valeur du pointeur d'être stockée dans un type de données "sûr", la connexion entre les segments de code unsafe peut être implémentée dans un code de haut niveau plus sûr - ou même dans un langage .NET ne prenant pas directement en charge les pointeurs .
La taille de IntPtr est spécifique à la plate-forme, mais ce détail doit rarement être pris en compte, car le système utilisera automatiquement la taille correcte.
Le nom "IntPtr" prête à confusion - quelque chose comme Handle
aurait peut-être été plus approprié. Ma supposition initiale était que "IntPtr" était un pointeur sur un entier. La documentation MSDN d'IntPtr entre dans des détails quelque peu cryptiques sans jamais fournir beaucoup d'informations sur la signification du nom.
Un IntPtr
est un pointeur avec deux limitations:
En d'autres termes, une IntPtr
est semblable à un void*
- mais avec la fonctionnalité supplémentaire qu'elle peut (mais ne devrait pas) être utilisée pour l'arithmétique de base du pointeur.
Afin de déréférencer une IntPtr
, vous pouvez soit le transformer en un véritable pointeur (opération qui ne peut être effectuée que dans des contextes "non sécurisés") ou vous pouvez le transmettre à une routine auxiliaire telle que celle fournie par la classe InteropServices.Marshal
. L’utilisation de la classe Marshal
donne l’illusion de sécurité, car elle n’exige pas que vous vous trouviez dans un contexte "non sécurisé" explicite. Cependant, cela ne supprime pas le risque de crash inhérent à l'utilisation de pointeurs.
Qu'est-ce qu'un pointeur?
Dans toutes les langues, un pointeur est un type de variable qui stocke une adresse de mémoire. Vous pouvez leur demander de vous indiquer le adresse ils pointent ou la valeur à l'adresse ils pointent .
Un pointeur peut être considéré comme une sorte de marque-page. Sauf que, au lieu d'être utilisé pour passer rapidement à une page d'un livre, un pointeur est utilisé pour suivre ou mapper des blocs de mémoire.
Imaginez la mémoire de votre programme exactement comme un grand tableau de 65535 octets.
Les pointeurs pointent docilement
Les pointeurs mémorisent chacun une adresse mémoire et, par conséquent, ils pointent chacun vers une adresse unique en mémoire.
En tant que groupe, les pointeurs se souviennent et se rappellent des adresses de mémoire, obéissant à toutes vos commandes ad nauseum.
Tu es leur roi.
Pointeurs en C #
Spécifiquement en C #, un pointeur est une variable entière qui stocke une adresse mémoire comprise entre 0 et 65534.
Également spécifiques à C #, les pointeurs sont de type int et donc signés.
Vous ne pouvez cependant pas utiliser d'adresses négativement numérotées, ni accéder à une adresse supérieure à 65534. Toute tentative dans ce sens déclenchera une exception System.AccessViolationException.
Un pointeur appelé MyPointer est déclaré comme suit:
int * MyPointer;
Un pointeur en C # est un int, mais les adresses mémoire en C # commencent à 0 et s'étendent jusqu'à 65534.
Les objets pointus doivent être manipulés avec un soin particulier
Le mot unsafe est destiné à vous faire peur, et pour une très bonne raison: les pointeurs sont des choses pointues, et des choses pointues, par exemple. les épées, les haches, les pointeurs, etc. doivent être manipulés avec un soin particulier.
Les pointeurs donnent au programmeur un contrôle étroit sur un système. Les erreurs commises risquent donc d'avoir des conséquences plus graves.
Pour utiliser des pointeurs, le code non sécurisé doit être activé dans les propriétés de votre programme, et les pointeurs doivent être utilisés exclusivement dans des méthodes ou des blocs marqués comme non sécurisés.
Exemple d'un bloc dangereux
unsafe
{
// Place code carefully and responsibly here.
}
Comment utiliser les pointeurs
Lorsque des variables ou des objets sont déclarés ou instanciés, ils sont stockés en mémoire.
int *MyPointer;
MyPointer = &MyVariable;
Une fois qu'une adresse est attribuée à un pointeur, les règles suivantes s'appliquent:
MyPointer = &MyVariable; // Set MyPointer to point at MyVariable
"MyPointer is pointing at " + *MyPointer;
Puisqu’un pointeur est une variable qui contient une adresse mémoire, cette adresse mémoire peut être stockée dans une variable pointeur.
Exemple de pointeurs utilisés avec précaution et responsabilité
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.
}
Notez que le type du pointeur est un int. En effet, C # interprète les adresses de mémoire sous forme de nombres entiers (int).
Pourquoi est-ce int au lieu de uint?
Il n'y a pas de bonne raison.
Pourquoi utiliser des pointeurs?
Les pointeurs sont très amusants. Avec une telle quantité d’ordinateur contrôlée par la mémoire, les pointeurs permettent aux programmeurs de mieux contrôler la mémoire de leur programme.
Surveillance de la mémoire.
Utilisez des pointeurs pour lire des blocs de mémoire et contrôler comment les valeurs pointées changent avec le temps.
Modifiez ces valeurs de manière responsable et suivez l’impact de vos modifications sur votre ordinateur.
MSDN nous dit:
Le type IntPtr est conçu pour être un entier dont la taille est spécifique à la plate-forme. C'est un instance de ce type est censé à être 32 bits sur du matériel 32 bits et systèmes d'exploitation et 64 bits sur Matériel et systèmes d'exploitation 64 bits.
Le type IntPtr peut être utilisé par langues qui supportent les pointeurs, et comme moyen commun de référence aux données entre les langues qui font et ne font pas pointeurs de support.
Les objets IntPtr peuvent également être utilisés pour tenir les poignées. Par exemple, instances de IntPtr sont largement utilisés dans le Classe System.IO.FileStream à contenir poignées de fichier.
Le type IntPtr est conforme à CLS, tandis que le type UIntPtr n'est pas. Seulement le type IntPtr est utilisé dans le commun temps d'exécution de la langue. Le type UIntPtr est fourni principalement pour maintenir symétrie architecturale avec le IntPtr type.
http://msdn.Microsoft.com/en-us/library/system.intptr(VS.71).aspx
Eh bien, voici la page MSDN qui traite de IntPtr
.
La première ligne se lit comme suit:
Un type spécifique à la plate-forme utilisé pour représenter un pointeur ou une poignée.
Quant à ce qu'est un pointeur ou une poignée, la page continue:
Le type IntPtr peut être utilisé par langues qui supportent les pointeurs, et comme moyen commun de référence aux données entre les langues qui font et ne font pas pointeurs de support.
Les objets IntPtr peuvent également être utilisés pour tenir les poignées. Par exemple, instances de IntPtr sont largement utilisés dans le Classe System.IO.FileStream à contenir poignées de fichier.
Un pointeur est une référence à une zone de mémoire contenant des données qui vous intéressent.
Un handle peut être un identifiant pour un objet et est passé entre les méthodes/classes lorsque les deux côtés doivent accéder à cet objet.
Une IntPtr
est un type value principalement utilisé pour contenir des adresses de mémoire ou des descripteurs. Un pointeur est une adresse mémoire. Un pointeur peut être saisi (par exemple int*
) ou non typé (par exemple void*
). Un descripteur Windows est une valeur généralement de la même taille (ou inférieure) à une adresse de mémoire et représentant une ressource système (telle qu'un fichier ou une fenêtre).