risposta

4

Bene, come sapete, la rappresentazione fisica del puntatore nullo di un dato tipo non è necessariamente un pattern a bit a zero. Quando si converte forzatamente un valore di un puntatore (qualsiasi puntatore) in un tipo intero, il risultato è definito dall'implementazione, ma normalmente (e questo è l'intento) il valore numerico del puntatore - l'indirizzo numerico - rimane invariato, se possibile. Ciò significa che se su una determinata piattaforma un puntatore nullo di tipo char * è rappresentato dal modello 0xBAADF00D (ad esempio), l'espressione sopra verrà valutata a 0xBAADF00D e non a zero. Certo, per quello avresti bisogno di una piattaforma con puntatori nulli non nulli. Personalmente non ho mai lavorato con tali piattaforme, anche se ho sentito parlare di un numero di piattaforme reali come quelle là fuori (come nel regno delle piattaforme embedded non è qualcosa di insolito).

Inoltre, come una nota aggiuntiva, i valori nulli di puntatore di tipo diverso possono avere diverse rappresentazioni fisiche, il che significa che, in teoria, è possibile ottenere valori diversi da (size_t) ((int *) 0), (size_t) ((char *) 0) e (size_t) ((double *) 0). Ma sarebbe una situazione piuttosto esotica, anche se perfettamente possibile dal punto di vista del linguaggio C astratto.

P.S. Leggi here (FAQ C) per alcuni esempi di piattaforme effettive con puntatori nulli diversi da zero.

+0

Capisco gli argomenti teorici (che spiegate bene), ma sto cercando esempi di sistemi reali in cui il cast di un puntatore nullo a un intero risulta in un valore diverso da zero in pratica. –

+0

@Bruce Christensen: vedere il collegamento alle domande frequenti in C in P.S. – AnT

+0

Interessante. Sembra che alcuni sistemi antichi usino rappresentazioni a bit non zero, ma non ci sono esempi moderni nelle FAQ. Sembra abbastanza certo che nessun sistema su cui Linux gira usa una rappresentazione diversa da zero, o la sua implementazione offsetof() si romperebbe (vedi http://google.com/codesearch/p?hl=it#huut-anHVuo/anonymous/kernel /v2.6/linux-2.6.20.tar.bz2%7CqE0cR-WvTpY/linux-2.6.20/include/linux/stddef.h&q=stddef.h%20linux-2.6). –

1

L'unica cosa che lo standard C richiede di rappresentanza runtime di un puntatore nullo è (6.3.2.3/3 "puntatori"):

... il puntatore risultante, chiamato un puntatore nullo, è garantito per confrontare non uguale a un puntatore a qualsiasi oggetto o funzione. La conversione di un puntatore nullo in un altro tipo di puntatore produce un puntatore nullo di quel tipo.

Eventuali due puntatori nulli devono essere uguali.

La tua domanda è interessante, però. Personalmente, non sono a conoscenza di una piattaforma che non utilizza il valore di runtime 0 per rappresentare un puntatore nullo. Tuttavia, lo standard non lo richiede, quindi se puoi evitare l'assunzione nel tuo codice, perché no?

Sarei interessato anche a chiunque conosca un sistema che utilizza un valore di runtime diverso da zero per un puntatore nullo.

0

questo non si applica a char* o anche C, ma una classe puntatore intelligente che indicizza in una matrice potrebbero scegliere di rappresentare NULL come -1 perché 0 è un indice di array valida.

Considerando l'idioma di memset(my_new_struct, 0, sizeof my_new_struct);, è improbabile che un sistema di debugging-centrico possa rompere tale identità.

1

Lo standard C99 indica che quando si converte un valore intero 0 in un puntatore, diventa un puntatore NULL. Quindi ((char*)0) è un puntatore NULL. Un puntatore NULL non deve avere una rappresentazione binaria effettiva di 0. Può essere, ad esempio, 0x12345678.

Lo standard C indica inoltre che quando si converte un puntatore NULL in una costante intera, il risultato è "definito dall'implementazione". In realtà, ciò che i compilatori fanno è semplicemente lanciare il valore numerico del puntatore al valore intero corrispondente, come ha detto AndreyT. Quindi nell'esempio sopra, il valore intero potrebbe essere 0x12345678, anche se tecnicamente potrebbe essere qualsiasi cosa (ad esempio il compilatore può dire "convertire un puntatore NULL in un valore intero ha come risultato il valore 0xDEADBEEF"). Nota che ciò significa che anche su piattaforme in cui il puntatore NULL ha il valore 0, il compilatore può convertirlo in un valore intero arbitrario durante la conversione. In realtà, tuttavia, nessun compilatore lo fa perché sarebbe abbastanza folle.

Quindi, sì, lo standard C consente un sacco di cose. In realtà, qualsiasi piattaforma su cui probabilmente lavorerai rappresenterà un puntatore NULL come 0 e la conversione di un puntatore NULL in un valore intero comporterà 0. Guarda here (section 1.14) per un elenco di alcune eccezioni di architetture (oscure) che non utilizzano 0 per un puntatore NULL.