Dal punto di vista dell'allocazione della memoria, hai ragione. Una variabile puntatore su un'architettura a 64 bit occupa 8 byte, indipendentemente dal tipo di puntatore.
Ma il compilatore C deve sapere di più su una variabile rispetto alla sua dimensione. Un'analogia: long
e float
tipicamente richiedono entrambi 4 byte (quindi perché avere tipi diversi ???), ma sicuramente dici al compilatore quale vuoi perché le loro operazioni si comportano diversamente .
Torna ai puntatori: c'è l'operatore *
per il dereferenziamento di un puntatore e l'operatore di indicizzazione []
per l'indirizzamento relativo ed entrambi devono conoscere il tipo di puntatore.
Per un puntatore dichiarato int *pi;
, un'istruzione come double x = *pi / 2
troncerà la divisione, mentre con un float *pf;
, float x = *pf / 2
ti darà un risultato frazionario. Quindi devi sicuramente dire al compilatore del tipo di puntatore, dato che alcuni comportamenti molto importanti dipendono da quelle informazioni .
E c'è l'aritmetica del puntatore, ad es. l'indirizzamento relativo fatto con l'operatore []
. Se abbiamo
char *pc = 0x12340; // Compiler will complain, as types don't match!
int *pi = 0x12340;
double *pd = 0x12340;
Quindi, pc[4]
sarà il carattere (byte) che trovi quattro caratteri dopo l'indirizzo 0x12340
, che si trova a 0x12344
. Ma troverai pd[4]
non a 0x12344
, ma a 0x12360
, 32 byte dopo l'indirizzo di base, poiché l'indicizzazione di un doppio puntatore conterà con incrementi di 8 byte invece di singoli byte. Ovviamente questo vale anche per tutte le aritmetiche dei puntatori, inclusi gli operatori +
e -
. Quindi, ancora una volta, devi dire al compilatore del tipo di puntatore per consentire l'aritmetica del puntatore corretta.
Una caratteristica importante del linguaggio C è che le informazioni sul tipo sono conservate solo nel compilatore. In fase di runtime, gli 8 byte del puntatore pi
in memoria non contengono l'informazione che pi
è un puntatore int
. È il compilatore che produce codice macchina diverso per operazioni su puntatori di tipi diversi.
Quindi, se ottieni un puntatore con valore 0x123456789ABCDEF0
e nessun'altra informazione, non puoi stabilire se è un double
, un int
o un puntatore a funzione (o qualsiasi altra cosa). Solo se il tuo codice compilato contiene un allegato di "debug", potresti trovare le informazioni lì che la variabile pi
è un puntatore int
, e se il tuo valore di puntatore 0x123456789ABCDEF0
proviene da quella variabile, allora sai di avere cercare un (4 byte?) int
a partire dall'indirizzo di 0x123456789ABCDEF0
se vuoi vedere il valore a cui pi
punta.
Ma questo allegato di debug non è assolutamente necessario per l'esecuzione del programma, è solo una cortesia per le persone che vogliono guardarsi dentro.