web-dev-qa-db-fra.com

Qu'est-ce qu'un IntPtr exactement?

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é?

154
Callum Rogers

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).

145
Sam Harwell

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.

57
Daniel Earwicker

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à.

35
bufferz

Une interprétation directe

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.

Une perspective alternative

Un IntPtr est un pointeur avec deux limitations:

  1. Il ne peut pas être directement référencé
  2. Il ne connaît pas le type de données qu'il pointe.

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.

31
nobar

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.

  • Déclarez un pointeur en utilisant le préfixe du symbole *. 

int *MyPointer;

  • Pour obtenir l'adresse d'une variable, utilisez le préfixe & symbole. 

MyPointer = &MyVariable;

Une fois qu'une adresse est attribuée à un pointeur, les règles suivantes s'appliquent:

  • Sans * le préfixe pour faire référence à l'adresse de la mémoire désignée en tant qu'int. 

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

  • Avec le préfixe * pour obtenir la valeur stockée à l'adresse de la mémoire pointée.

"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.

11
Knickerless-Noggins

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

7
Zyphrax

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.

5
ChrisF

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). 

0
cdiggins