example - ¿Qué hace((struct name*) 0)-> member) en C?
structs in java (4)
En muchos compiladores, la expresión anterior arrojará un char*
que, si bien no es un puntero válido, tiene una o ambas de las siguientes propiedades:
Al convertir el puntero directamente en un tipo entero, se producirá el desplazamiento del miembro indicado dentro de la estructura.
Restando
(char*)0
del puntero producirá el desplazamiento del miembro indicado dentro de la estructura.
Tenga en cuenta que el estándar C no impone requisitos con respecto a lo que puede suceder si el código forma un valor de puntero no válido a través de los medios anteriores o cualquier otro, incluso si el código no intenta desreferenciar el puntero. Si bien muchos compiladores producen punteros con las cualidades indicadas, dicho comportamiento no es universal. Incluso en plataformas donde existe una relación natural clara entre punteros y enteros, algunos proveedores de compiladores pueden decidir que tener programas se comporten como lo implica esa relación, sería más "eficiente" tener al compilador en lugar de asumir que un programa nunca lo hará. recibir entradas que causarían la generación de punteros no válidos y, en consecuencia, que cualquier código que solo sería relevante si se recibieran tales entradas debería omitirse.
Esta pregunta ya tiene una respuesta aquí:
¿Qué hace ((struct name *) 0) -> member) en C?
La verdadera declaración C que encontré fue esta:
(char *) &((struct name *)0)->member)
Este es un truco para obtener el desplazamiento del miembro de struct
llamado member
. La idea detrás de este enfoque es hacer que el compilador calcule la dirección del member
suponiendo que la estructura en sí está ubicada en la dirección cero.
El uso de offsetof
ofrece una alternativa más legible a esta sintaxis:
size_t offset = offsetof(struct name, member);
(struct name *)0
está lanzando 0
al puntero al struct name
.
&((struct name *)0)->member)
obtiene la dirección del miembro member
.
(char *) &((struct name *)0)->member)
está lanzando esa dirección a char *
.
En caso de que alguien piense que la expresión anterior está desreferenciando un puntero NULL
, entonces tenga en cuenta que no hay desreferencia aquí. Todo es para obtener la dirección del number
de miembro.
(struct name*)0
le da un puntero struct.
((struct name*)0)->member
le proporciona el miembro de la estructura a la que apunta el puntero.
Añadiendo &
le da la dirección de ese miembro, y por último
(char *)
es convertir la dirección obtenida a un puntero char.