The code &((struct name *)0)->b
is indeed known as the "offsetof" operation and is in fact a well-known C macro.
The idea is that if a
is a structure of type A
then &a.b
is equal to the address of a
plus the offset of b
in a
. Since here NULL is used instead of the address of a
, the result is just the offset of b
in structures of type A
.
According to Wikipedia,
This works by casting a null pointer into a pointer to structure st,
and then obtaining the address of member m within said structure.
While this implementation works correctly in many compilers, it has
undefined behavior according to the C standard,2 since it involves a
dereference of a null pointer (although, one might argue that no
dereferencing takes place, because the whole expression is calculated
at compile time)
So let's look at the expression in printf
step-by-step.
The expression (unsigned int) & ( (struct name *)0 )->b))
calculates offset of b
in struct name
as described above and casts the result to an integer. The result should be equal to sizeof(long)
on most platforms.
The (char*)na
in the code casts na
, which is a pointer to struct name
to a char pointer. This is required because sizeof(char)
can be assumed to be 1 while sizeof(*na)
is larger than 1. What we want to do is to use the address of *na
as a raw numerical address instead of doing pointer arithmetic, so that if for example na==0x1234
, then the result of ((char*)na + 4)
is equal to 0x1234 + 4 = 0x1238
.
The sum results in a memory address. That address is equal to the address of member variable b
in the object na
, and is of type char *
. Knowing that, the last step is to cast the address back to int *
(because the type of b
is int
) and then to dereference the result (once again, we know that it points to b
). The final outcome is the value of b
, which is then printed.