I have smoked a significant amount of 420 but still can't understand how this macro function works: #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
>>1 As experienced developer of void.h this macro is a piece of cake. offsetof gets you offset struct_type<>member distance, when you apply offset to the ptr, you get to offset 0 which is the address of container of the ptr(all ptr are assumed to be member type). In pseudocode: container_ptr=ptr - offset_from_containertype_to_member.
>>2 What's the point of the typeof stuff on the first line? It's cast to char * for byte pointer arithmetic anyway, so wouldn't char *__mptr = (char *)(ptr); work fine?
Name:
Anonymous2016-12-30 10:06
>>8 I presume it's for rudimentary typechecking: the compiler will complain if ptr is not, in fact, a pointer to a value of type.member's type.
// creates a struct ptr from a struct embedded as a member of a containing struct; see the example I made below // the first line is instantiating a properly typed pointer, which is used in the second step // to do pointer arithmetic to place the input ptr in the appropriate location for the "new" struct #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) // ^^ byte difference between start of the struct, [type], and [member] // subtracting this from [ptr] yields a valid pointer to the start of [type] // see this diagram of offsets: // struct X { // ... 0 // ... 4 // *__mptr 8 // } // __mptr - 8 == (struct X*)...
>>18 it implies container_of will also work in haskell(with plain structs of course) since Haskell has full access to raw pointers with IO and malloc. i.e. you can create a C struct, allocate it and get the container_member offset 0 (the parent struct) just like in C
Name:
Anonymous2017-01-05 17:58
It's a disgusting violation of type safety, which is not allowed on good hardware. C and Linux wouldn't even run on it.