- Articolo
Gli operatori puntatore consentono di prendere l'indirizzo di una variabile (&
), dereferenziare un puntatore (*
), confrontare i valori dei puntatori e aggiungere o sottrarre puntatori e numeri interi.
Utilizzare i seguenti operatori per lavorare con i puntatori:
- Unariooperatore: per ottenere l'indirizzo di una variabile
- Unario* (indicazione indiretta del puntatore)operatore: per ottenere la variabile puntata da un puntatore
- IL-> (accesso membri)E[] (accesso all'elemento)operatori
- Operatori aritmetici+, -, ++ e --
- Operatori di confronto==, !=, <, >, <= e >=
Per informazioni sui tipi di puntatore, vedereTipi di puntatori.
Nota
Qualsiasi operazione con i puntatori richiede un filepericolosocontesto. Il codice che contiene blocchi unsafe deve essere compilato con il fileConsenti blocchi non sicuriopzione del compilatore.
Indirizzo dell'operatore &
L'unario&
operatore restituisce l'indirizzo del suo operando:
non sicuro{ int numero = 27; int* pointerToNumber = № Console.WriteLine($"Valore della variabile: {numero}"); Console.WriteLine($"Indirizzo della variabile: {(long)pointerToNumber:X}");}// L'output è simile a:// Valore della variabile: 27// Indirizzo della variabile: 6C1457DBD4
L'operando di&
operatore deve essere una variabile fissa.Fissole variabili sono variabili che risiedono in posizioni di memoria che non sono interessate dal funzionamento dinetturbino. Nell'esempio precedente, la variabile localenumero
è una variabile fissa, perché risiede nello stack. Vengono chiamate le variabili che risiedono in posizioni di archiviazione che possono essere interessate dal Garbage Collector (ad esempio, trasferite).mobilevariabili. I campi oggetto e gli elementi dell'array sono esempi di variabili mobili. Puoi ottenere l'indirizzo di una variabile mobile se lo "aggiusti" o "blocchi" con adichiarazione fissa. L'indirizzo ottenuto è valido solo all'interno del blocco di afisso
dichiarazione. L'esempio seguente mostra come utilizzare afisso
dichiarazione e il&
operatore:
non sicuro{ byte[] byte = { 1, 2, 3 }; fixed (byte* pointerToFirst = &bytes[0]) { // L'indirizzo memorizzato in pointerToFirst // è valido solo all'interno di questo blocco di istruzioni fixed. }}
Non puoi ottenere l'indirizzo di una costante o di un valore.
Per ulteriori informazioni sulle variabili fisse e mobili, vedere ilVariabili fisse e mobilisezione delSpecifica del linguaggio C#.
Il binario&
operatore calcola ilAND logicodei suoi operandi booleani o ilAND logico bit a bitdei suoi operandi interi.
Operatore di riferimento indiretto del puntatore *
L'operatore di indirezione del puntatore unario*
ottiene la variabile a cui punta il suo operando. È anche noto come operatore di dereferenziazione. L'operando di*
l'operatore deve essere di tipo puntatore.
non sicuro{ carattere lettera = 'A'; char* pointerToLetter = &letter; Console.WriteLine($"Valore della variabile `letter`: {letter}"); Console.WriteLine($"Indirizzo della variabile `letter`: {(long)pointerToLetter:X}"); *pointerToLettera = 'Z'; Console.WriteLine($"Valore della variabile `letter` dopo l'aggiornamento: {letter}");}// L'output è simile a:// Valore della variabile `letter`: A// Indirizzo della variabile `letter` : DCB977DDF4// Valore della variabile `lettera` dopo l'aggiornamento: Z
Non puoi applicare il*
operatore a un'espressione di tipovuoto*
.
Il binario*
operatore calcola ilProdottodei suoi operandi numerici.
Operatore di accesso ai membri del puntatore ->
IL->
operatore combinapuntatore indirettoEaccesso dei membri. Cioè, seX
è un puntatore di tipoT*
Esi
è un membro accessibile di typeT
, espressione della forma
x->y
è equivalente a
(*x).y
Nell'esempio seguente viene illustrato l'utilizzo di->
operatore:
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; Coordinate* p = &coordinate; p->X = 3; p->Y = 4; Console.WriteLine(p->ToString()); // output: (3, 4) }}
Non puoi applicare il->
operatore a un'espressione di tipovuoto*
.
Operatore di accesso all'elemento puntatore []
Per un'espressioneP
di un tipo puntatore, un accesso elemento puntatore del formp[n]
viene valutato come*(p+n)
, DoveN
deve essere di un tipo convertibile in modo implicito inint
,uint
,lungo
, OTesta
. Per informazioni sul comportamento del+
operatore con i puntatori, vedere ilAggiunta o sottrazione di un valore integrale a o da un puntatoresezione.
L'esempio seguente mostra come accedere agli elementi dell'array con un puntatore e il[]
operatore:
unsafe{ char* pointerToChars = stackalloc char[123]; for (int i = 65; i < 123; i++) { pointerToChars[i] = (char)i; } Console.Write("Lettere maiuscole: "); for (int i = 65; i < 91; i++) { Console.Write(pointerToChars[i]); }}// Output:// Lettere maiuscole: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Nell'esempio precedente, aespressione stackallocalloca un blocco di memoria nello stack.
Nota
L'operatore di accesso all'elemento puntatore non verifica la presenza di errori fuori limite.
Non puoi usare[]
per l'accesso all'elemento puntatore con un'espressione di tipovuoto*
.
Puoi anche usare il[]
operatore peraccesso all'elemento dell'array o all'indicizzatore.
Operatori aritmetici puntatori
È possibile eseguire le seguenti operazioni aritmetiche con i puntatori:
- Aggiungere o sottrarre un valore integrale a o da un puntatore
- Sottrai due puntatori
- Incrementa o decrementa un puntatore
Non è possibile eseguire tali operazioni con puntatori di tipovuoto*
.
Per informazioni sulle operazioni aritmetiche supportate con tipi numerici, vedereOperatori aritmetici.
Aggiunta o sottrazione di un valore integrale a o da un puntatore
Per un puntatoreP
di tipoT*
e un'espressioneN
di un tipo implicitamente convertibile inint
,uint
,lungo
, OTesta
, l'addizione e la sottrazione sono definite come segue:
- Entrambi
p + n
En + p
le espressioni producono un puntatore di tipoT*
che risulta dall'addizionen * dimensionedi(T)
all'indirizzo indicato daP
. - IL
p - n
espressione produce un puntatore di tipoT*
che risulta dalla sottrazionen * dimensionedi(T)
dall'indirizzo fornito daP
.
ILoperatore sizeofottiene la dimensione di un tipo in byte.
Nell'esempio seguente viene illustrato l'utilizzo di+
operatore con un puntatore:
unsafe{ const int Count = 3; int[] numeri = new int[Conteggio] { 10, 20, 30 }; fixed (int* pointerToFirst = &numbers[0]) { int* pointerToLast = pointerToFirst + (Count - 1); Console.WriteLine($"Valore {*pointerToFirst} all'indirizzo {(long)pointerToFirst}"); Console.WriteLine($"Valore {*pointerToLast} all'indirizzo {(long)pointerToLast}"); }}// L'output è simile a:// Valore 10 all'indirizzo 1818345918136// Valore 30 all'indirizzo 1818345918144
Sottrazione del puntatore
Per due puntatorip1
Ep2
di tipoT*
, l'espressionep1 - p2
produce la differenza tra gli indirizzi dati dap1
Ep2
diviso perdimensionedi(T)
. Il tipo di risultato èlungo
. Questo è,p1 - p2
è calcolato come((lungo)(p1) - (lungo)(p2)) / sizeof(T)
.
L'esempio seguente mostra la sottrazione del puntatore:
unsafe{ int* numeri = stackalloc int[] { 0, 1, 2, 3, 4, 5 }; int* p1 = &numeri[1]; int* p2 = &numeri[5]; Console.WriteLine(p2 - p1); // uscita: 4}
Incremento e decremento del puntatore
IL++
operatore di incrementoaggiunge1 al suo operando puntatore. IL--
operatore di decrementosottrae1 dal suo operando puntatore.
Entrambi gli operatori sono supportati in due forme: postfix (p++
EP--
) e prefisso (++pag
E--P
). Il risultato dip++
EP--
è il valore diP
Primal'operazione. Il risultato di++pag
E--P
è il valore diP
Dopol'operazione.
L'esempio seguente mostra il comportamento di entrambi gli operatori di incremento postfisso e prefisso:
unsafe{ int* numeri = stackalloc int[] { 0, 1, 2 }; int* p1 = &numeri[0]; int* p2 = p1; Console.WriteLine($"Prima dell'operazione: p1 - {(lungo)p1}, p2 - {(lungo)p2}"); Console.WriteLine($"Incremento suffisso di p1: {(long)(p1++)}"); Console.WriteLine($"Incremento prefisso di p2: {(long)(++p2)}"); Console.WriteLine($"Dopo l'operazione: p1 - {(long)p1}, p2 - {(long)p2}");}// L'output è simile a// Prima dell'operazione: p1 - 816489946512, p2 - 816489946512// Incremento suffisso di p1: 816489946512// Incremento prefisso di p2: 816489946516// Dopo operazione: p1 - 816489946516, p2 - 816489946516
Operatori di confronto puntatore
Puoi usare il==
,!=
,<
,>
,<=
, E>=
operatori per confrontare operandi di qualsiasi tipo di puntatore, inclusivuoto*
. Questi operatori confrontano gli indirizzi forniti dai due operandi come se fossero numeri interi senza segno.
Per informazioni sul comportamento di tali operatori per operandi di altri tipi, vedere ilOperatori di uguaglianzaEOperatori di confrontoarticoli.
Precedenza dell'operatore
L'elenco seguente ordina gli operatori relativi ai puntatori a partire dalla precedenza più alta fino a quella più bassa:
- Incremento suffisso
x++
e decrementoX--
operatori e il->
E[]
operatori - Incremento del prefisso
++ x
e decremento--X
operatori e il&
E*
operatori - Additivo
+
E-
operatori - Confronto
<
,>
,<=
, E>=
operatori - Uguaglianza
==
E!=
operatori
Usa le parentesi,()
, per modificare l'ordine di valutazione imposto dalla precedenza dell'operatore.
Per l'elenco completo degli operatori C# ordinati per livello di precedenza, vedere ilPrecedenza dell'operatoresezione delOperatori C#articolo.
Sovraccaricabilità dell'operatore
Un tipo definito dall'utente non può eseguire l'overload degli operatori relativi al puntatore&
,*
,->
, E[]
.
Specifica del linguaggio C#
Per ulteriori informazioni, vedere le seguenti sezioni delSpecifica del linguaggio C#:
- Variabili fisse e mobili
- L'indirizzo dell'operatore
- Puntatore indiretto
- Accesso membro puntatore
- Accesso all'elemento puntatore
- Aritmetica del puntatore
- Incremento e decremento del puntatore
- Confronto puntatore
Guarda anche
- Riferimento C#
- Operatori ed espressioni C#
- Codice non sicuro, tipi di puntatore e puntatori a funzione
- parola chiave non sicura
- dichiarazione fissa
- espressione stackalloc
- operatore sizeof