From: Rusty Russell Date: Mon, 12 Dec 2011 03:20:05 +0000 (+1030) Subject: container_of: add container_off_var macro X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=87f505a56eae7ef2a03a76b5b412d6bc46c58aae container_of: add container_off_var macro Based on patch by Andrey Smirnov : There is are certain use-cases when it is necessary to know the offset of the member in a structure's memory layout. One such use-case can be seen in `ccan/list/list.h' in macros `list_for_each' and `list_for_each_safe'. This commit implements said functionality with `container_of_var_off' macro. Renamed container_of_var_off -> container_off_var now we have container_off. --- diff --git a/ccan/container_of/container_of.h b/ccan/container_of/container_of.h index ea8f1dd3..1c9d147a 100644 --- a/ccan/container_of/container_of.h +++ b/ccan/container_of/container_of.h @@ -82,10 +82,27 @@ #define container_of_var(member_ptr, container_var, member) \ container_of(member_ptr, typeof(*container_var), member) #else -#define container_of_var(member_ptr, container_var, member) \ - ((void *)((char *)(member_ptr) \ - - ((char *)&(container_var)->member \ - - (char *)(container_var)))) +#define container_of_var(member_ptr, container_var, member) \ + ((void *)((char *)(member_ptr) - \ + container_off_var(container_var, member))) +#endif + +/** + * container_off_var - get offset of a field in enclosing structure + * @container_var: a pointer to a container structure + * @member: the name of a member within the structure. + * + * Given (any) pointer to a structure and a its member name, this + * macro does pointer subtraction to return offset of member in a + * structure memory layout. + * + */ +#if HAVE_TYPEOF +#define container_off_var(var, member) \ + container_off(typeof(*var), member) +#else +#define container_off_var(var, member) \ + ((char *)&(var)->member - (char *)(var)) #endif #endif /* CCAN_CONTAINER_OF_H */ diff --git a/ccan/container_of/test/run.c b/ccan/container_of/test/run.c index 96ef483c..5da440a1 100644 --- a/ccan/container_of/test/run.c +++ b/ccan/container_of/test/run.c @@ -12,7 +12,7 @@ int main(int argc, char *argv[]) int *intp = &foo.a; char *charp = &foo.b; - plan_tests(6); + plan_tests(8); ok1(container_of(intp, struct foo, a) == &foo); ok1(container_of(charp, struct foo, b) == &foo); ok1(container_of_var(intp, &foo, a) == &foo); @@ -20,5 +20,7 @@ int main(int argc, char *argv[]) ok1(container_off(struct foo, a) == 0); ok1(container_off(struct foo, b) == offsetof(struct foo, b)); + ok1(container_off_var(&foo, a) == 0); + ok1(container_off_var(&foo, b) == offsetof(struct foo, b)); return exit_status(); }