Tipi di puntatori (Guida per programmatori C#)
In un contesto unsafe, un tipo può essere un tipo di puntatore, un tipo di valore o un tipo di riferimento. La dichiarazione di un tipo di puntatore può assumere uno dei seguenti formati:
type* identifier;
void* identifier; //allowed but not recommended
I tipi seguenti possono essere tipi di puntatore:
sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal o bool.
Qualsiasi tipo enum.
Qualsiasi tipo di puntatore.
Qualsiasi tipo struct definito dall'utente che contenga campi solo di tipi non gestiti.
I tipi di puntatore non ereditano da object. Non sono inoltre previste conversioni tra essi e object. Con i puntatori non sono inoltre supportate le operazioni di boxing e unboxing. È tuttavia possibile eseguire conversioni tra tipi di puntatore diversi e tra tipi di puntatore e tipi integrali.
Quando si dichiarano più puntatori nella stessa dichiarazione, l'asterisco (*) viene scritto solo con il tipo sottostante. Non viene utilizzato come prefisso di ogni nome di puntatore. Di seguito è riportato un esempio.
int* p1, p2, p3; // Ok
int *p1, *p2, *p3; // Invalid in C#
Un puntatore non può puntare a un riferimento o a struct che contiene riferimenti, perché un riferimento a un oggetto può essere sottoposto a procedure di Garbage Collection anche se un puntatore punta a esso. Il Garbage Collector non tiene traccia degli altri tipi di puntatore che puntano all'oggetto.
Il valore della variabile del puntatore di tipo myType* è l'indirizzo di una variabile di tipo myType. Di seguito sono riportati alcuni esempi di dichiarazioni di tipi di puntatore:
Esempio |
Descrizione |
---|---|
int* p |
p è un puntatore a un Integer. |
int** p |
p è un puntatore a un puntatore a un Integer. |
int*[] p |
p è una matrice unidimensionale di puntatori a Integer. |
char* p |
p è un puntatore a un carattere. |
void* p |
p è un puntatore a un tipo sconosciuto. |
Per accedere al contenuto nella posizione a cui punta la variabile del puntatore, è possibile utilizzare *, ovvero l'operatore di riferimento indiretto a puntatore. Si consideri ad esempio la seguente dichiarazione:
int* myVariable;
L'espressione *myVariable indica la variabile int individuata all'indirizzo contenuto in myVariable.
Esistono vari esempi dei puntatori negli argomenti Istruzione fixed (Riferimenti per C#) e Conversioni di puntatori (Guida per programmatori C#). Nell'esempio seguente viene illustrata la necessità della parola chiave unsafe e dell'istruzione fixed e come incrementare un puntatore interno. È possibile incollare il codice nella funzione Main di un'applicazione console per eseguirlo. Ricordarsi di abilitare il codice unsafe in Progettazione progetti. Scegliere Progetto, Proprietà nella barra dei menu e quindi selezionare Consenti codice di tipo unsafe nella scheda Compilazione).
// 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
Non è possibile applicare l'operatore di riferimento indiretto a un puntatore di tipo void*. È tuttavia possibile eseguire un cast per convertire un puntatore void in qualsiasi altro tipo e viceversa.
Un puntatore può essere null. Se l'operatore di riferimento indiretto viene applicato a un puntatore Null, si otterrà un comportamento definito dall'implementazione.
Tenere presente che il passaggio di puntatori tra metodi può generare un comportamento non definito, ad esempio se un puntatore viene restituito a una variabile locale tramite un parametro Out o Ref oppure come risultato della funzione. Se il puntatore è stato impostato in un blocco fisso, la variabile a cui punta potrebbe non essere più fissa.
Nella tabella riportata di seguito sono elencati gli operatori e le istruzioni che è possibile utilizzare con i puntatori in un contesto unsafe:
Operatore/istruzione |
Utilizzo |
---|---|
* |
Esegue il riferimento indiretto al puntatore. |
-> |
Accede a un membro di struct tramite un puntatore. |
[] |
Indicizza un puntatore. |
& |
Ottiene l'indirizzo di una variabile. |
++ e -- |
Incrementa e decrementa puntatori. |
+ e - |
Utilizza l'aritmetica dei puntatori. |
==, !=, <, >, <= e >= |
Confronta puntatori. |
stackalloc |
Alloca memoria nello stack. |
Istruzione fixed |
Corregge temporaneamente una variabile per consentire di trovarne l'indirizzo. |
Specifiche del linguaggio C#
Per altre informazioni, vedere la Specifiche del linguaggio C#. La specifica del linguaggio costituisce il riferimento ufficiale principale per la sintassi e l'uso di C#.
Vedere anche
Riferimenti
Codice unsafe e puntatori (Guida per programmatori C#)
Conversioni di puntatori (Guida per programmatori C#)
Espressioni puntatore (Guida per programmatori C#)
Istruzione fixed (Riferimenti per C#)
stackalloc (Riferimenti per C#)
Boxing e unboxing (Guida per programmatori C#)