23 March 2008 - 11:12Implementing offsetof() as a macro
File this under neat/stupid C tricks:
/* From linux/include/stddef.h */
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
The offsetof(t,m) macro is supposed to return the offset of member m in type (structure) t. This is useful for a variety of things, particular finding the address of the beginning of a structure given the address of any element in it.
Some compilers implement offsetof() natively and the code above will use the compiler’s offsetof() if it exists. But if it doesn’t it performs the pointer arithmetic tricks seen above. It works by taking address 0 and casting it to a pointer (pointer to whatever structure we care about). Then it uses the structure element operator -> to obtain the value of member, then applies the address-of operator to obtain the address of the structure member relative to a structure beginning at address zero, and thus relative to the beginning of the structure. Then it simply casts this value into a generic size_t, indicating an address offset. Note that while this code appears to dereference a null (0) pointer, it only applies the address-of operator to the result so no actual dereferencing is performed at runtime.
The Linux kernel uses this in its linked list implementation. The doubly linked list implementation uses a structure called list_head which contains forward and backward pointers. To use the linked list, you simply need to include the list_head as an element anywhere in whatever structure you want to use as the data associated with the list. You can even include it multiple times, and the data can be a member of multiple lists. You manipulate the list using the list_head structures and when you want a pointer to the data you simply use the list_entry() macro which uses offsetof() to determine where the list_head exists within the data structure then subtracts it to yield the beginning of the structure. Neat and elegant!
For details about the kernel linked list, check out Linux Kernel Linked List Explained, which does a good job describing the various functions which allow easy linked list manipulation.
No Comments | Tags: computers


