Remarque
L’accès à cette page requiert une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page requiert une autorisation. Vous pouvez essayer de modifier des répertoires.
Les opérateurs liés aux pointeurs vous permettent de prendre l’adresse d’une variable (&), de déréférencer un pointeur (*), de comparer les valeurs des pointeurs, et d’ajouter ou de soustraire des pointeurs et des entiers.
La documentation de référence du langage C# décrit la version la plus récente du langage C#. Il contient également la documentation initiale des fonctionnalités dans les préversions publiques pour la prochaine version du langage.
La documentation identifie toute fonctionnalité introduite en premier dans les trois dernières versions de la langue ou dans les préversions publiques actuelles.
Conseil / Astuce
Pour savoir quand une fonctionnalité a été introduite en C#, consultez l’article sur l’historique des versions du langage C#.
Utilisez les opérateurs suivants pour utiliser des pointeurs :
- Opérateur unaire
&(address-of) : pour obtenir l’adresse d’une variable - Opérateur unaire
*(indirection de pointeur) : pour obtenir la variable pointée par un pointeur - Opérateurs
->(accès aux membres) et[](accès aux éléments) - Opérateurs arithmétiques
+,-,++et-- - Opérateurs de comparaison
==,!=,<,>,<=et>=
Pour plus d’informations sur les types de pointeurs, consultez Types pointeur.
Notes
Toutes les opérations impliquant des pointeurs nécessitent un contexte unsafe. Vous devez compiler le code qui contient des blocs non sécurisés avec l’option du compilateur AllowUnsafeBlocks .
Opérateur adresse de &
L’opérateur unaire & retourne l’adresse de son opérande :
unsafe
{
int number = 27;
int* pointerToNumber = &number;
Console.WriteLine($"Value of the variable: {number}");
Console.WriteLine($"Address of the variable: {(long)pointerToNumber:X}");
}
// Output is similar to:
// Value of the variable: 27
// Address of the variable: 6C1457DBD4
L’opérande de l’opérateur & doit être une variable fixe.
Les variables fixes sont des variables qui résident dans des emplacements de stockage que le garbage collector n’affecte pas. Dans l’exemple précédent, la variable locale est une variable number fixe, car elle réside sur la pile. Les variables qui résident dans des emplacements de stockage que le garbage collector peut affecter (par exemple, le déplacement) sont appelées variables mobiles . Les champs d’objet et les éléments de tableau sont des exemples de variables déplaçables. Vous pouvez obtenir l’adresse d’une variable mobile si vous « corrigez » ou « épingler », à l’aide d’une fixed instruction. L’adresse obtenue est uniquement valide à l’intérieur du bloc d’une instruction fixed. L’exemple suivant montre comment utiliser une instruction fixed et l’opérateur & :
unsafe
{
byte[] bytes = { 1, 2, 3 };
fixed (byte* pointerToFirst = &bytes[0])
{
// The address stored in pointerToFirst
// is valid only inside this fixed statement block.
}
}
Vous ne pouvez pas obtenir l’adresse d’une constante ou d’une valeur.
Pour plus d’informations sur les variables fixes et déplaçables, consultez la section Variables fixes et déplaçables de la spécification du langage C#.
L’opérateur binaire & calcule la logique AND de ses opérandes booléens, ou la logique AND au niveau du bit de ses opérandes de type intégral.
Opérateur d’indirection de pointeur *
L’opérateur * d’indirection de pointeur unaire accède à la variable à laquelle son opérande pointe. Il est également appelé « opérateur de déréférence ». L’opérande de l’opérateur * doit être un type de pointeur.
unsafe
{
char letter = 'A';
char* pointerToLetter = &letter;
Console.WriteLine($"Value of the `letter` variable: {letter}");
Console.WriteLine($"Address of the `letter` variable: {(long)pointerToLetter:X}");
*pointerToLetter = 'Z';
Console.WriteLine($"Value of the `letter` variable after update: {letter}");
}
// Output is similar to:
// Value of the `letter` variable: A
// Address of the `letter` variable: DCB977DDF4
// Value of the `letter` variable after update: Z
Vous ne pouvez pas appliquer l’opérateur * à une expression de type void*.
L’opérateur binaire * calcule le produit de ses opérandes numériques.
Opérateur d’accès aux membres du pointeur ->
L’opérateur -> associe l’indirection de pointeur à l’accès aux membres. S’il x s’agit d’un pointeur de type T* et y est un membre accessible de type T, expression du formulaire
x->y
équivaut à :
(*x).y
L’exemple suivant illustre l’utilisation de l’opérateur -> :
public struct Coords
{
public int X;
public int Y;
public override string ToString() => $"({X}, {Y})";
}
public class PointerMemberAccessExample
{
public static unsafe void Main()
{
Coords coords;
Coords* p = &coords;
p->X = 3;
p->Y = 4;
Console.WriteLine(p->ToString()); // output: (3, 4)
}
}
Vous ne pouvez pas utiliser l’opérateur -> sur une expression de type void*.
Opérateur d’accès aux éléments de pointeur []
Pour une expression p d’un type de pointeur, un accès à l’élément pointeur du formulaire p[n] est évalué en tant que *(p + n). La valeur n doit être d’un type implicitement convertible en int, uint, longou ulong. Pour plus d’informations sur le comportement de l’opérateur + avec les pointeurs, consultez la section Addition ou soustraction d’une valeur intégrale dans un pointeur.
L’exemple suivant montre comment accéder aux éléments de tableau à l’aide d’un pointeur et de l’opérateur [] :
unsafe
{
char* pointerToChars = stackalloc char[123];
for (int i = 65; i < 123; i++)
{
pointerToChars[i] = (char)i;
}
Console.Write("Uppercase letters: ");
for (int i = 65; i < 91; i++)
{
Console.Write(pointerToChars[i]);
}
}
// Output:
// Uppercase letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Dans l’exemple précédent, une expression stackalloc alloue un bloc de mémoire sur la pile.
Notes
L’opérateur d’accès aux éléments de pointeur ne recherche pas les erreurs de dépassement des limites.
Vous ne pouvez pas utiliser [] pour l’accès aux éléments de pointeur avec une expression de type void*.
Vous pouvez également utiliser l’opérateur [] pour l’accès aux éléments de tableau ou à l’indexeur.
Opérateurs arithmétiques de pointeur
Vous pouvez effectuer les opérations arithmétiques suivantes avec des pointeurs :
- Ajouter ou soustraire une valeur intégrale dans un pointeur
- Soustraire deux pointeurs
- Incrémenter ou décrémenter un pointeur
Vous ne pouvez pas effectuer ces opérations avec des pointeurs de type void*.
Pour plus d’informations sur les opérations arithmétiques prises en charge à l’aide de types numériques, consultez les opérateurs arithmétiques.
Ajouter ou soustraire une valeur intégrale dans un pointeur
Pour un pointeur p de type T* et une expression n d’un type implicitement convertible en int, uint, longou ulong, ajout et soustraction fonctionnent comme suit :
- Les deux
p + netn + pvous donnent un pointeur de typeT*. Vous obtenez ce pointeur en ajoutantn * sizeof(T)à l’adresse àplaquelle pointe. - L’expression
p - nvous donne un pointeur de typeT*. Vous obtenez ce pointeur en soustrayantn * sizeof(T)l’adresse àplaquelle pointe.
L’opérateursizeof obtient la taille d’un type en octets.
L’exemple suivant montre comment utiliser l’opérateur + avec un pointeur :
unsafe
{
const int Count = 3;
int[] numbers = new int[Count] { 10, 20, 30 };
fixed (int* pointerToFirst = &numbers[0])
{
int* pointerToLast = pointerToFirst + (Count - 1);
Console.WriteLine($"Value {*pointerToFirst} at address {(long)pointerToFirst}");
Console.WriteLine($"Value {*pointerToLast} at address {(long)pointerToLast}");
}
}
// Output is similar to:
// Value 10 at address 1818345918136
// Value 30 at address 1818345918144
Soustraction de pointeur
Pour deux pointeurs p1 et p2 de type T*, l’expression p1 - p2 vous donne la différence entre les adresses qui p1 et p2 pointent, divisées par sizeof(T). Le résultat est de type long. En d’autres termes, p1 - p2 est calculé comme ((long)(p1) - (long)(p2)) / sizeof(T).
L’exemple suivant montre la soustraction de pointeur :
unsafe
{
int* numbers = stackalloc int[] { 0, 1, 2, 3, 4, 5 };
int* p1 = &numbers[1];
int* p2 = &numbers[5];
Console.WriteLine(p2 - p1); // output: 4
}
Incrémenter et décrémenter des pointeurs
L’opérateur d’incrémentation ++ajoute 1 à son opérande de pointeur. L’opérateur de décrémentation --soustrait 1 de son opérande de pointeur.
Les deux opérateurs prennent en charge deux formes : postfix (p++ et p--) et préfixe (++p et --p). Le résultat de p++ et p-- est la valeur de pavant l’opération. Le résultat de ++p et --p est la valeur de paprès l’opération.
L’exemple suivant montre le comportement des opérateurs d’incrémentation suffixés et préfixés :
unsafe
{
int* numbers = stackalloc int[] { 0, 1, 2 };
int* p1 = &numbers[0];
int* p2 = p1;
Console.WriteLine($"Before operation: p1 - {(long)p1}, p2 - {(long)p2}");
Console.WriteLine($"Postfix increment of p1: {(long)(p1++)}");
Console.WriteLine($"Prefix increment of p2: {(long)(++p2)}");
Console.WriteLine($"After operation: p1 - {(long)p1}, p2 - {(long)p2}");
}
// Output is similar to
// Before operation: p1 - 816489946512, p2 - 816489946512
// Postfix increment of p1: 816489946512
// Prefix increment of p2: 816489946516
// After operation: p1 - 816489946516, p2 - 816489946516
Opérateurs de comparaison de pointeur
Vous pouvez utiliser les opérateurs ==, !=, <, >, <= et >= pour comparer des opérandes de tout type de pointeur, y compris void*. Ces opérateurs comparent les adresses données par les deux opérandes comme s’il s’agit d’entiers non signés.
Pour plus d’informations sur le comportement de ces opérateurs pour les opérandes d’autres types, consultez les articles Opérateurs d’égalité et Opérateurs de comparaison.
Priorité des opérateurs
La liste suivante présente les opérateurs relatifs aux pointeurs par ordre de précédence, de la plus élevée à la plus basse :
- Opérateurs suffixés d’incrémentation
x++et de décrémentationx--, ainsi que les opérateurs->et[] - Opérateurs préfixés d’incrémentation
++xet de décrémentation--x, ainsi que les opérateurs&et* - Opérateurs additifs
+et- - Opérateurs de comparaison
<,>,<=et>= - Opérateurs d’égalité
==et!=
Utilisez des parenthèses (()) pour modifier l’ordre d’évaluation imposé par la précédence des opérateurs.
Pour obtenir la liste complète des opérateurs C# classés par niveau de priorité, consultez la section Priorité des opérateurs de l’article Opérateurs C#.
Capacité de surcharge de l’opérateur
Vous ne pouvez pas surcharger les opérateurs &liés au pointeur, *->et [] dans un type défini par l’utilisateur.
spécification du langage C#
Pour plus d’informations, consultez les sections suivantes de la spécification du langage C# :
- Variables fixes et déplaçables
- address-of, opérateur
- Indirection de pointeur
- Accès aux membres de pointeur
- Accès aux éléments de pointeur
- Arithmétique des pointeurs
- Incrémentation et décrémentation des pointeurs
- Comparaison de pointeurs