It's finding the byte offset of a particular member of a struct
. For example, if you had the following structure:
struct MyStruct
{
double d;
int i;
void *p;
};
Then you'd have offsetOf(MyStruct, d) == 0
, offsetOf(MyStruct, i) == 8
, and offsetOf(MyStruct, p) == 12
(that is, the member named d
is 0 bytes from the start of the structure, etc.).
The way that it works is it pretends that an instance of your structure exists at address 0 (the ((a*)(0))
part), and then it takes the address of the intended structure member and casts it to an integer. Although dereferencing an object at address 0 would ordinarily be an error, it's ok to take the address because the address-of operator &
and the member dereference ->
cancel each other out.
It's typically used for generalized serialization frameworks. If you have code for converting between some kind of wire data (e.g. bytes in a file or from the network) and in-memory data structures, it's often convenient to create a mapping from member name to member offset, so that you can serialize or deserialize values in a generic manner.
offsetof
macro is incorrect. They should cast tosize_t
, notint
, and they should probably subtract(char*)0
from the result before casting even though it's a null pointer constant. – Chris Lutz