I have been searching very long and hard (links at the very end) for an explanation of the implementation of the offsetof MACRO :
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
Particularly, the dereferencing of NULL to obtain the offset of the member in the structure. Many articles gloss over the reason by saying that the NULL pointer is actually never really dereferenced, but that doesn't make sense to me.
Here are some of the links I have tried understanding:
What I'm looking for and trying to understand is a step by step , broken down understanding of how the compiler interprets the MACRO definition, which will eventually explain how a NULL pointer is not actually being dereferenced.
EDIT: Even though other questions answered my query, they dindt make sense to me, as pointed out in the original post. The answer by @dasblinkenlight sheds light on the exact problem I had with ansers to other questions i.e how is it that we're not actually dereferencing the pointer .
Particularly, the dereferencing of NULL to obtain the offset of the member in the structure.
There is no dereferencing of the pointer going on, because the effect of operator ->
are undone by the operator &
:
NULL
: ((TYPE *)0)->MEMBER
&
in front of it makes it an address computation: &((TYPE *)0)->MEMBER
Many articles gloss over the reason by saying that the NULL pointer is actually never really dereferenced, but that doesn't make sense to me.
Consider this example as an illustration:
int a;
int *p = &a;
int b = *p; // <<== This is a dereference
int *q = &(*p); // <<== This is not a dereference
The two operators, *
and &
, undo the effect of each other. Operator ->
is a "syntactic sugar" on top of *
and .
, so &
can undo its effects as well.
When a compiler sees an expression somePointer->a
it takes the numeric value of the pointer somePointer
, adds the offset of member a
, and learns the place in memory on which you can operate. There are three things you could do to a place in memory:
Items 1 and 2 (reading and writing) constitute dereferencing. Item 3, however, is not dereferencing, because the memory at the specific address is not accessed.
The macro essentially asks the compiler to compute the address of member a
assuming that the base address is zero. The address of a
returned would naturally be equal to a
's offset. All you need to do is take its address, which is what you do with the operator &
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With