What does ((struct name *)0)->member) do in C?
The actual C statement I came across was this:
(char *) &((struct name *)0)->member)
What does ((struct name *)0)->member) do in C?
The actual C statement I came across was this:
(char *) &((struct name *)0)->member)
This is a trick for getting the offset of struct
's member called member
. The idea behind this approach is to have the compiler compute the address of member
assuming that the structure itself is located at address zero.
Using offsetof
offers a more readable alternative to this syntax:
size_t offset = offsetof(struct name, member);
(struct name *)0
is casting 0
to pointer to struct name
.
&((struct name *)0)->member)
is getting the address of member member
.
(char *) &((struct name *)0)->member)
is casting that address to char *
.
In case anyone thinks that the above expression is dereferencing a NULL
pointer, then note that there is no dereferencing here. It's all for getting the address of member number
.
(struct name*)0
gives you a struct pointer.
((struct name*)0)->member
gives you the member of the struct where the pointer points to.
Adding &
gives you the address of that member, and lastly
(char *)
is to cast the obtained address to a char pointer.
On many compilers, the above expression will yield a char*
which, while it isn't a valid pointer, has a one or both of the following properties:
Casting the pointer directly to an integer type will yield the displacement of the indicated member within the structure.
Subtracting (char*)0
from the pointer will yield the displacement of the indicated member within the structure.
Note that the C Standard imposes no requirements with regard to what may happen if code forms an invalid pointer value via the above means or any other, even if the code makes no attempt to dereference the pointer. While many compilers produce pointers with the indicated qualities, such behavior is not universal. Even on platforms where there exists a clear natural relationship between pointers and integers, some compiler vendors may decide that having programs behave as implied by such a relationship, it would be more "efficient" to instead have the compiler to assume that a program will never receive inputs that would cause the generation of invalid pointers and, consequently, that any code which would only be relevant if such inputs were received should be omitted.