2010-04-02 12 views
5

de Linux stddef.h define como offsetof():¿Por qué restar el puntero nulo en offsetof()?

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

mientras que el artículo de Wikipedia sobre offsetof() (http://en.wikipedia.org/wiki/Offsetof) lo define como:

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

Por qué restar (char *)0 en la versión de Wikipedia? ¿Hay algún caso en el que eso realmente marque la diferencia?

+0

No debe usar/estudiar código que pueda invocar un comportamiento no definido, como el anterior. Una implementación puede usar tales hack skanky porque saben qué tipos de comportamiento indefinido funcionan en secreto. Pero lo que "secretamente funciona" no es totalmente portátil. – CTMacUser

Respuesta

6

La primera versión convierte un puntero en un entero con un molde, que no es portátil.

La segunda versión es más portátil en una amplia variedad de compiladores, ya que depende del aritmético del puntero por parte del compilador para obtener un resultado entero en lugar de un tipocast.

Por cierto, yo era el editor que agregaba el código original a la entrada Wiki, que era el formulario de Linux. Los editores posteriores lo cambiaron a la versión más portátil.

+0

Gracias por la respuesta. Pregunta de seguimiento "¿(size_t) ((char *) 0) alguna vez no se evalúa a 0?" publicado en http://stackoverflow.com/questions/2581522/does-size-tchar-0-ever-not-evaluate-to-0 –

+0

Interesante, pero es la segunda expresión realmente más portátil, desde la aritmética del puntero en punteros nulos ¿es indefinido? –

+1

Es más portátil en el sentido de que funciona en más CPU. Ser indefinido (según el estándar) no significa que no puede funcionar para algunas arquitecturas específicas. –

4

El estándar no requiere el puntero NULL para evaluar el patrón de bits 0 pero puede evaluar a un valor específico de plataforma.

Haciendo la resta garantiza que cuando se convierte a un valor entero, NULL es 0.

+2

Esa no es la razón; cualquier constante razonable que no sea '0 'también podría ser utilizada. Ver mi respuesta a continuación. –

Cuestiones relacionadas