Perché è necessario specificare il tipo di dati che un puntatore manterrà, se tutti i puntatori sono uguali [duplicato]

3

Perché è necessario specificare il tipo di dati il cui indirizzo verrà mantenuto, se tutti i puntatori sono uguali. Dal momento che tutti i puntatori memorizzano gli indirizzi. Inoltre, la quantità di spazio che un puntatore richiederà in memoria dipende dal fatto che la macchina sia a 32 o 64 bit.

Supponiamo che il mio puntatore ptr memorizzi l'indirizzo di un int e che la mia macchina sia a 64-bit. Quindi, all'interno del mio puntatore ptr, vedo un indirizzo a 8 byte (64 bit), 0x123456789ABCDEF0.

Supponiamo di avere una casella etichettata come ptr e che contenga questo (0x123456789ABCDEF0) no che è l'indirizzo di un int. Ora, questo indirizzo (0x123456789ABCDEF0) non specifica se è un indirizzo di un int o char o float o double o qualsiasi altra cosa è solo un indirizzo nella RAM. Quindi, come fa chiunque altro a sapere che il puntatore punta a un int se gli viene solo detto che ptr è un puntatore e l'indirizzo che contiene è (0x123456789ABCDEF0)?

    
posta Ahmad Nasir 10.07.2018 - 18:28
fonte

1 risposta

14

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.

    
risposta data 10.07.2018 - 22:34
fonte

Leggi altre domande sui tag