Types pointeur (Guide de programmation C#)
Dans un contexte unsafe, un type peut être un type pointeur, un type valeur ou un type référence. La déclaration d'un type pointeur peut prendre l'une des formes suivantes :
type* identifier;
void* identifier; //allowed but not recommended
Chacun des types suivants peut être un type pointeur :
sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal ou bool.
Tout type enum.
Tout type pointeur.
Tout type struct défini par l'utilisateur qui contient des champs de types unmanaged uniquement.
Les types pointeur n'héritent pas de object et aucune conversion n'existe entre types pointeur et object. Par ailleurs, le boxing et l'unboxing ne prennent pas en charge les pointeurs. Cependant, vous pouvez effectuer des conversions entre différents types pointeur ainsi qu'entre des types pointeur et des types intégraux.
Lorsque vous déclarez plusieurs pointeurs dans la même déclaration, l'astérisque (*) est écrit conjointement au type sous-jacent uniquement, il n'est pas utilisé en tant que préfixe de chaque nom de pointeur. Par exemple :
int* p1, p2, p3; // Ok
int *p1, *p2, *p3; // Invalid in C#
Un pointeur ne peut pas pointer vers une référence ou un struct qui contient des références, car une référence d'objet peut être récupérée par le récupérateur de mémoire, même si un pointeur pointe vers elle. Le récupérateur de mémoire ne se préoccupe pas de savoir si un objet est pointé par des types pointeur.
La valeur de la variable pointeur de type myType* est l'adresse d'une variable de type myType. Les éléments suivants sont des exemples de déclarations de type pointeur :
Exemple |
Description |
---|---|
int* p |
p est un pointeur vers un entier. |
int** p |
p est un pointeur vers un pointeur vers un entier. |
int*[] p |
p est un tableau unidimensionnel de pointeurs vers des entiers. |
char* p |
p est un pointeur vers un caractère. |
void* p |
p est un pointeur vers un type inconnu. |
L'opérateur d'indirection de pointeur * peut être utilisé pour accéder au contenu à l'emplacement vers lequel pointe la variable pointeur. Observez par exemple la déclaration suivante :
int* myVariable;
L'expression *myVariable désigne la variable int trouvée à l'adresse contenue dans myVariable.
Plusieurs exemples de pointeurs sont présentés dans les rubriques fixed, instruction (référence C#) et Conversions de pointeur (Guide de programmation C#). L'exemple suivant montre la nécessité d'un pointeur intérieur pour le mot clé unsafe et les instructions fixed, et comment l'incrémenter. Vous pouvez coller ce code dans la fonction Main d'une application console pour l'exécuter. (N'oubliez pas d'activer le code unsafe dans le Concepteur de projets ; choisissez Projet, Propriétés dans la barre de menus, puis sélectionnez Autoriser le code unsafe dans l'onglet Générer.)
// Normal pointer to an object.
int[] a = new int[5] {10, 20, 30, 40, 50};
// Must be in unsafe code to use interior pointers.
unsafe
{
// Must pin object on heap so that it doesn't move while using interior pointers.
fixed (int* p = &a[0])
{
// p is pinned as well as object, so create another pointer to show incrementing it.
int* p2 = p;
Console.WriteLine(*p2);
// Incrementing p2 bumps the pointer by four bytes due to its type ...
p2 += 1;
Console.WriteLine(*p2);
p2 += 1;
Console.WriteLine(*p2);
Console.WriteLine("--------");
Console.WriteLine(*p);
// Deferencing p and incrementing changes the value of a[0] ...
*p += 1;
Console.WriteLine(*p);
*p += 1;
Console.WriteLine(*p);
}
}
Console.WriteLine("--------");
Console.WriteLine(a[0]);
Console.ReadLine();
// Output:
//10
//20
//30
//--------
//10
//11
//12
//--------
//12
L'opérateur d'indirection ne peut pas être appliqué à un pointeur de type void*. Toutefois, vous pouvez utiliser un cast pour convertir un pointeur void en n'importe quel autre type pointeur, et inversement.
Un pointeur peut être null. Le fait d'appliquer un opérateur d'indirection à un pointeur Null donne lieu à un comportement défini par l'implémentation.
Sachez que le passage de pointeurs entre méthodes peut engendrer un comportement non défini. Par exemple, retourner un pointeur à une variable locale via un paramètre Out ou Ref ou en tant que résultat de fonction. Si le pointeur a été défini dans un bloc fixed, la variable vers laquelle il pointe peut ne plus être fixed.
Le tableau suivant répertorie les opérateurs et les instructions qui peuvent fonctionner sur des pointeurs dans un contexte unsafe :
Opérateur/Instruction |
Utilisation |
---|---|
* |
Exécute l'indirection de pointeur. |
-> |
Accède à un membre d'un struct via un pointeur. |
[] |
Indexe un pointeur. |
& |
Obtient l'adresse d'une variable. |
++ et -- |
Incrémente et décrémente les pointeurs. |
+ et - |
Exécute des opérations arithmétiques sur les pointeurs. |
==, !=, <, >, <=, et >= |
Compare des pointeurs. |
stackalloc |
Alloue de la mémoire sur la pile. |
Instruction fixed |
Résout temporairement une variable afin de pouvoir rechercher son adresse. |
Spécification du langage C#
Pour plus d'informations, voir la Spécification du langage C#. La spécification du langage est la source de référence pour la syntaxe C# et son utilisation.
Voir aussi
Référence
Pointeurs et code unsafe (Guide de programmation C#)
Conversions de pointeur (Guide de programmation C#)
Expressions de pointeur (Guide de programmation C#)
fixed, instruction (référence C#)
Boxing et unboxing (Guide de programmation C#)