Più puntatori possono fare riferimento alla stessa variabile in C?

5

È una stranezza del C che spesso fa inciampare i principianti ma sembra magico una volta fatto clic: puoi avere una dozzina di puntatori che fissano tutti lo stesso indirizzo di memoria.

Considera questo scenario. Dichiari un numero intero “i”. Quindi dichiari tre puntatori p, q e r. Li assegni tutti all’indirizzo “i”.

Guarda l’ultima riga. Non è necessario che r conosca direttamente i. Punta semplicemente a qualunque cosa stia puntando “p”. E “p” punta a “i”. Quindi anche “r” punta a “i”.

L’operatore di assegnazione qui copia l’indirizzo, non il valore. Quando esegui “r = p”, non stai copiando il numero intero all’interno di “i”. Stai copiando la posizione di memoria che contiene p.

Dopo l’esecuzione di questo codice, “i” ha essenzialmente quattro nomi. Puoi accedervi tramite “i”. Puoi accedervi tramite *p. Puoi accedervi tramite *q. Oppure puoi accedervi tramite *r.

Non esiste un limite tecnico al numero di puntatori che puoi accumulare in questo modo.

Perché è importante

Questa non è solo sintassi accademica. Cambia il modo in cui pensi al flusso di dati.

Nei linguaggi con riferimenti rigorosi agli oggetti, la copia di un oggetto spesso crea una nuova istanza in memoria. In C, copiare un puntatore è economico. È solo un indirizzo di memoria. Veloce. Minuscolo.

Ciò consente a più parti del codice di manipolare gli stessi dati senza duplicazioni. Cambia *p e *q vedono la modifica immediatamente.

Stai creando alias per la memoria.

Il rischio di alias

È qui che l'”aspetto interessante” diventa una responsabilità.

Se p, q e r puntano tutti a i, ognuno di essi può modificare i.

Ora “i” è 10. “q” è 10. “ r” è 10.

Ma cosa succede se dimentichi che anche “r” sta guardando “i”? Potresti presumere che “i” sia stabile perché non l’hai toccato direttamente. Hai toccato solo “*q”.

È una risorsa condivisa. E le risorse condivise sono il luogo in cui vivono condizioni di competizione e sovrascritture impreviste.

Come prevenire gli effetti collaterali indesiderati

Se vuoi assicurarti che un puntatore non sovrascriva accidentalmente i dati destinati a un altro, usi “const”.

Ora r può leggere “i”. Può indicarlo. Non può cambiarlo.

Questo è il modo in cui imposti i confini in una lingua che si fida di te per gestire la memoria manualmente.

Dove si inserisce questo nella programmazione dei sistemi

Vedi questo modello ovunque nel codice di sistema.

Le strutture del kernel spesso hanno più puntatori allo stesso blocco di controllo. I driver di dispositivo associano lo stesso registro hardware a nomi logici diversi.

Comprendere che i puntatori sono solo etichette per gli indirizzi aiuta a eseguire il debug di questi problemi. Quando la memoria si corrompe, traccia i puntatori. Chi altro