I'm having trouble grasping the meaning behind the following:
#define MAKE(z, w) (int)(&(((z *)0)->w))
Can anyone fill me in?
Specifically, I'm confused on the ((z *)0) part. I'm not exactly sure
what that would give me.
The expression `(z *)0` is a null pointer of type `z*`. This isn't
quite the same as a "zero-valued" pointer (e.g., a null pointer may have
some arbitrary implementation-specific bit pattern that serves as a
trap), but the writer makes the assumption that null = zero.
Assuming for the moment that `(z *)0` gives you a zero-valued pointer,
the expression `((z *)0)->w` pretends there is a structure of type `z`
at address 0, and accesses the `w` field of the structure. The address
of this field is then taken, and the resulting address is cast to `int`.
E.g., given the structure definition
struct foo{
int32_t bar;
int32_t bas;
};
and plausible assumptions about structure layout and byte size,
`MAKE(foo foo, bas)` is intended to yield 4.
(Oh, and if differently-typed pointers have different representations on
your system, this will break horribly in very interesting ways.)
See also the `offsetof()` macro in <stddef.h>, which accomplishes this
same thing, but is defined by your compiler provider in a way which is
guaranteed to work on your machine.
By the way: Is there a portable way to get a zero-valued pointer? To
take a concrete example, assume a system where uintptr_t is defined, and
on which
union intptr {
void *p;
uintptr_t i;
};
/* ... */
union intptr u = {.p = 0};
assert(u.i == 0xDEADBEEF);
holds. On this system, is there an initializer for a pointer value for
which
union intptr v = {.p = ZERO_PTR};
assert(u.i == 0);
holds?
This should work:
#define ZERO_PTR ((intptr){.i = 0}).p
but is there a way to not require the union definition?
I'm wondering if `(void *)((uintptr_t)0)` might do the trick -- or is
the void* <-> uintptr_t conversion defined to map null to zero?
--Joel