Qual è la differenza tra un puntatore che punta alla posizione 0x0 e un puntatore impostato su NULL?


12

Un puntatore che punta a 0x0000 è uguale a un puntatore impostato su NULL? Se il valore NULL è definito nel linguaggio C, in quale posizione viene tradotto fisicamente? È uguale a 0x0000. Dove posso trovare maggiori dettagli su questi concetti?


1
Questo è già stato richiesto su StackTranslate.it: stackoverflow.com/questions/1296843/… . Penso che sia al limite per noi, ma sono disposto a dargli il beneficio del dubbio per il momento.
ChrisF

Risposte:


12

Un punto che la maggior parte delle risposte qui non si rivolge, almeno non esplicitamente, è che un puntatore null è un valore esistente durante l'esecuzione e una costante puntatore null è un costrutto sintattico che esiste nel codice sorgente C.

Una costante puntatore null , come afferma correttamente la risposta di Karlson, è o un'espressione di costante intera con il valore 0 (un semplice 0è l'esempio più comune) o un'espressione simile lanciata su void*(come (void*)0).

NULLè una macro, definita in <stddef.h>e diverse altre intestazioni standard, che si espande in una costante puntatore null definita dall'implementazione . L'espansione è in genere o 0o ((void*)0)(le parentesi esterne sono necessarie per soddisfare le altre regole linguistiche).

Quindi un valore letterale 0, se utilizzato in un contesto che richiede un'espressione di tipo puntatore, valuta semprenull pointer un valore di puntatore univoco che non indica alcun oggetto. Ciò non implica nulla sulla rappresentazione di un puntatore nullo . I puntatori null sono molto comunemente rappresentati come all-bit-zero, ma possono essere rappresentati come qualsiasi cosa. Ma anche se un puntatore null è rappresentato come 0xDEADBEEF, 0o (void*)0è ancora una costante puntatore null .

Questa risposta alla domanda su StackOverflow copre questo bene.

Ciò implica, tra l'altro, che memset()o calloc(), che può impostare una regione di memoria su all-bit-zero, non imposterà necessariamente alcun puntatore in quella regione su puntatori nulli. È probabile che lo facciano sulla maggior parte delle implementazioni, ma il linguaggio non lo garantisce.

Non so perché questa domanda non sia considerata un duplicato di questa , o come sia attuale qui.


1
Uno dei miei problemi con il design e l'evoluzione di C è che la cifra zero ha continuato ad essere utilizzata come rappresentazione non deprecata di un puntatore nullo. Nei primi giorni del linguaggio (ad esempio prima dell'avvento di cose come i prototipi di funzioni), i puntatori e gli interi erano sufficientemente intercambiabili che l'uso di "0" per un puntatore nullo era semplice e "funzionava". Una volta diventato necessario distinguere tra la quantità intera zero e un puntatore nullo, tuttavia, la rappresentazione "0" avrebbe dovuto essere deprecata a favore di una sequenza di parole chiave o operatore.
supercat

Questo significa che il puntatore NULL può effettivamente puntare a una posizione quando viene assegnato NULL a seconda della piattaforma? La costante puntatore null può essere un costrutto sintattico ma cosa succede esattamente quando il codice viene eseguito? Supponiamo che questo costrutto sintattico sia stato compilato sulla piattaforma GNU / Linux. Qual è il valore del puntatore quando gli assegniamo NULL? In che modo questo indirizzo differisce da qualsiasi altro indirizzo?
Arpith,

1
@Arpith: l'assegnazione NULLo qualsiasi costante puntatore null a un oggetto puntatore imposta il valore dell'oggetto su un puntatore null . A livello di macchina, potrebbe anche indicare un pezzo di memoria valido. Dereferenziare un puntatore nullo ha un comportamento indefinito; l'accesso a un pezzo di memoria all'indirizzo 0x0000000è un comportamento valido, come letteralmente qualsiasi altra cosa. Tale indirizzo differisce da qualsiasi altro indirizzo per (a) confronto uguale a NULL, e (b) confronto disuguale con qualsiasi puntatore a un oggetto C. Un puntatore nullo è un valore di puntatore arbitrario utilizzato per indicare che non punta a nulla.
Keith Thompson,

1
A livello di macchina, può indicare una parte di memoria valida, ma nella maggior parte degli ambienti C punterà a memoria non valida in modo che qualsiasi tentativo di utilizzare il puntatore comporti una trappola / errore / eccezione hardware. Di solito è solo sulle piattaforme hardware molto più semplici --- quelle senza supporto per la gestione della memoria --- dove un puntatore NULL punta a una posizione di memoria valida.
Solomon Slow,

7

Ogni piattaforma là fuori è libera di definire NULL a proprio piacimento.

Secondo lo standard C, se si assegna zero a un puntatore, questo verrà convertito in un valore NULL (per quella piattaforma.) Tuttavia, se si prende un puntatore NULL e lo si lancia in int, non ci sono garanzie che si otterrà zero su ogni piattaforma là fuori. Il fatto è tuttavia che sulla maggior parte delle piattaforme sarà zero.

Informazioni su quella roba si può trovare in linguaggio C Specification . Una fonte, la cui affidabilità non posso garantire, è questa: http://www.winapi.co.kr/pds/doc/ISO-C-FDIS.1999-04.pdf


2
Se scelgono di staccarsi dallo standard, sono liberi di ridefinire NULL pointer constant. Per quanto ne so non ci sono compilatori là fuori che lo fanno.
Karlson,

Esiste un compilatore là fuori che non implementa NULL come 0? Ed è garantito che NULL valuti falso?
ugoren,

NULL è garantito per valutare falso dallo standard. Non so se esiste un compilatore (piattaforma, in realtà) che non implementa NULL come 0, e ne dubito seriamente, ma lo standard non lo proibisce, quindi chi lo sa.
Mike Nakis,

C'è confusione tra la rappresentazione della "costante puntatore null" astratta (come menzionato nella specifica) in memoria, che può essere come piace al produttore della piattaforma e la definizione di NULLmacro, che deve espandersi 0in C ++ e in 0o (void *)0in C, perché questa è la vera "costante puntatore null".
Jan Hudec,

Sebbene NULL possa in teoria essere definito come qualsiasi cosa, esiste comunque una garanzia da parte dello standard che una costante int con il valore 0 convertito in un puntatore risulterà in un puntatore nullo (ISO 9899: 1999 6.3.2.3/3). La macro NULL di stddef.h deve essere un puntatore null (7.17 / 3), quindi sarebbe molto oneroso per il compilatore non implementare NULL come 0 o (void *) 0.

1

È definito nel linguaggio C perché non esiste un indirizzo macchina invariabile a cui corrisponda. Se così fosse, non avremmo bisogno di un'astrazione da esso! Anche se sulla maggior parte delle piattaforme, NULL potrebbe alla fine essere implementato come 0 di un tipo o altro, è semplicemente errato supporre che sia universalmente così, se ti interessa la portabilità.



0

Secondo la sezione del documento standard C6.3.2.3 :

Un'espressione di costante intera con il valore 0, o un'espressione simile lanciata per digitare void *, viene chiamata costante di puntatore null.55) Se una costante di puntatore null viene convertita in un tipo di puntatore, il puntatore risultante, chiamato puntatore null, è garantito per confrontare ineguali con un puntatore a qualsiasi oggetto o funzione.

Finora non ho visto un compilatore che si è separato da questo.


@ PéterTörök Hai ragione, è un tifoso. :)
Karlson,

1
Sì, ma nota che non dice nulla sul puntatore che ha effettivamente un valore numerico di 0. Potrebbe non farlo, sebbene sulla maggior parte delle piattaforme lo faccia.
Jan Hudec,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.