2010-04-02 16 views
5

di Linux stddef.h definisce offsetof() come:Perché sottrarre un puntatore nullo in offsetof()?

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 

, mentre alle voci di Wikipedia offsetof() (http://en.wikipedia.org/wiki/Offsetof) lo definisce come:

#define offsetof(st, m) \ 
    ((size_t) ((char *)&((st *)(0))->m - (char *)0)) 

Perché sottrarre (char *)0 nella versione Wikipedia? C'è qualche caso in cui ciò potrebbe davvero fare la differenza?

+0

Non si dovrebbe utilizzare/studiare codice che potrebbe richiedere un comportamento non definito, come sopra. Un'implementazione può utilizzare tali hack skanky perché sanno quali tipi di comportamento non definito funzionano segretamente. Ma ciò che "segretamente funziona" non è assolutamente portatile. – CTMacUser

risposta

6

La prima versione converte un puntatore in un intero con un cast, che non è portatile.

La seconda versione è più portabile su una più ampia varietà di compilatori, perché si basa sul puntatore aritmetico del compilatore per ottenere un risultato intero anziché un typecast.

BTW, ero l'editor che ha aggiunto il codice originale alla voce Wiki, che era il modulo Linux. Gli editori successivi lo hanno cambiato nella versione più portatile.

+0

Grazie per la risposta. Domanda successiva "Does (size_t) ((char *) 0) non viene mai valutata a 0?" pubblicato su http://stackoverflow.com/questions/2581522/does-size-tchar-0-ever-not-evaluate-to-0 –

+0

Interessante - ma la seconda espressione è davvero più portatile, poiché l'aritmetica del puntatore su puntatori nulli è indefinito? –

+1

È più portatile nel senso che funziona su più CPU. Essere indefinito (secondo lo standard) non significa che non possa funzionare per alcune architetture specifiche. –

4

Lo standard non richiede che il puntatore NULL valuti il ​​modello di bit 0 ma può valutare un valore specifico della piattaforma.

Facendo la sottrazione garantisce che quando convertito in un valore intero, NULL è 0.

+2

Non è questo il motivo; potrebbe anche essere usata qualsiasi costante ragionevole diversa da "0". Vedi la mia risposta qui sotto. –

Problemi correlati