Come più puntatori fanno riferimento a un singolo indirizzo in C

12

C ti consente di creare una folla attorno a una singola posizione di memoria. Non devi accontentarti di un puntatore. Qualsiasi numero di puntatori può puntare allo stesso indirizzo. Questo non è un bug. È una caratteristica di come C gestisce i riferimenti alla memoria.

Consideriamo una semplice variabile intera “i”. Puoi dichiarare tre puntatori distinti: p, q e r. Il codice è semplice.

Guarda l’ultima riga. “r” punta alla stessa cosa a cui punta “p”. E poiché a “p” è già assegnato l’indirizzo “i”, anche “r” punta effettivamente a “i”.

L’operatore di assegnazione copia l’indirizzo dal lato destro al lato sinistro. Non copia il valore memorizzato a quell’indirizzo. Copia la posizione stessa. Questa è una distinzione fondamentale nell’aritmetica dei puntatori.

Dopo l’esecuzione, “i” ha quattro nomi. Puoi fare riferimento al numero intero come “i”. Puoi modificarlo tramite *p. Puoi leggerlo tramite *q. Puoi anche accedervi usando *r.

Non esiste alcun limite al numero di puntatori che possono contenere lo stesso indirizzo. Potresti dichiarare s, t e u se lo desideri. Sarebbero tutti solo alias per lo stesso pezzo di memoria.

Questa flessibilità è importante. Consente alle funzioni di condividere riferimenti ai dati senza copiare strutture di grandi dimensioni. Abilita strutture dati complesse in cui più nodi puntano allo stesso figlio. Rende la gestione delle risorse in C più efficiente.

Ma introduce anche dei rischi. Se un puntatore modifica il valore, tutti i puntatori vedono la modifica. Non c’è isolamento. Devi stare attento. Un puntatore cambia il numero intero. Gli altri lo vedono subito.

La variabile i ora ha quattro nomi: i, *p, *q e *r.

Questa è l’aritmetica base dei puntatori. È fondamentale per comprendere i modelli di memoria C. Ma è anche il momento in cui le cose si fanno complicate. Più riferimenti allo stesso indirizzo significano più modi per corrompere i dati.

Puoi concatenare le assegnazioni dei puntatori all’infinito. s = r; t = s;. Tutto rimanda a “i”. Al compilatore non importa. Il tempo di esecuzione non importa. Sono solo indirizzi di memoria.

Perché questo è importante per gli utenti di tutti i giorni? Se stai scrivendo codice C, fai affidamento su questo. Se stai eseguendo il debug di un arresto anomalo, spesso questo è il colpevole. Gli errori use-after-free prosperano in ambienti in cui i puntatori vengono riassegnati ma non annullati.

L’efficienza ha un costo. Complessità. Devi tenere traccia di chi possiede i dati. Chi è autorizzato a modificarlo. Con più puntatori, il monitoraggio diventa più difficile.

Ma il potere è innegabile. Puoi passare puntatori alle funzioni. Modificare il valore. La variabile originale riflette il cambiamento. È così che il C ottiene la semantica di riferimento senza oggetti.

È un concetto semplice. Copia l’indirizzo. Non copiare il valore. Lascia che più nomi si riferiscano a una posizione. Usalo saggiamente.