È possibile inizializzare un puntatore C a NULL?
TL; DR Sì, molto.
L' affermazione effettiva fatta sulla guida si legge come
D'altra parte, se si utilizza solo l'assegnazione iniziale singola int *my_int_ptr = 2;
, il programma tenterà di riempire il contenuto della posizione di memoria indicata da my_int_ptr
con il valore 2. Poiché my_int_ptr
è pieno di spazzatura, può essere qualsiasi indirizzo. [...]
Ebbene, essi sono sbagliato, hai ragione.
Per la dichiarazione, ( ignorando, per ora, il fatto che il puntatore alla conversione di numeri interi è un comportamento definito dall'implementazione )
int * my_int_ptr = 2;
my_int_ptr
è una variabile (di tipo puntatore a int
), ha un indirizzo proprio (tipo: indirizzo del puntatore a numero intero), stai memorizzando un valore di 2
in quell'indirizzo .
Ora, my_int_ptr
essendo un tipo di puntatore, possiamo dire, punta al valore di "tipo" nella posizione di memoria indicata dal valore contenuto my_int_ptr
. Quindi, stai essenzialmente assegnando il valore della variabile del puntatore, non il valore della posizione di memoria a cui punta il puntatore.
Quindi, per concludere
char *x=NULL;
inizializza la variabile del puntatore x
su NULL
, non il valore nell'indirizzo di memoria a cui punta il puntatore .
Questo è lo stesso di
char *x;
x = NULL;
Espansione:
Ora, essendo rigorosamente conforme, un'affermazione come
int * my_int_ptr = 2;
è illegale, in quanto implica la violazione dei vincoli. Per essere chiari,
my_int_ptr
è una variabile puntatore, tipo int *
- una costante intera,
2
ha tipo int
, per definizione.
e non sono tipi "compatibili", quindi questa inizializzazione non è valida perché viola le regole dell'assegnazione semplice, menzionate nel capitolo §6.5.16.1 / P1, descritte nella risposta di Lundin .
Nel caso qualcuno sia interessato a come l'inizializzazione è collegata a semplici vincoli di assegnazione, citando C11
, capitolo §6.7.9, P11
L'inizializzatore per uno scalare deve essere una singola espressione, facoltativamente racchiusa tra parentesi graffe. Il valore iniziale dell'oggetto è quello dell'espressione (dopo la conversione); si applicano gli stessi vincoli e conversioni di tipo dell'assegnazione semplice, considerando il tipo dello scalare come versione non qualificata del suo tipo dichiarato.
int *x = whatever;
fa e cosaint *x; *x = whatever;
fa.int *x = whatever;
effettivamente si comporta comeint *x; x = whatever;
, no*x = whatever;
.