Index: kernel/generic/include/adt/hash_table.h
===================================================================
--- kernel/generic/include/adt/hash_table.h	(revision e037cf3733f322897cbfc63ce44277485f52af9b)
+++ kernel/generic/include/adt/hash_table.h	(revision cd6287931f05186767f2ccee516423a0342dfad2)
@@ -41,4 +41,5 @@
 #include <stdbool.h>
 #include <macros.h>
+#include <member.h>
 
 /** Opaque hash table link type. */
Index: kernel/generic/include/adt/list.h
===================================================================
--- kernel/generic/include/adt/list.h	(revision e037cf3733f322897cbfc63ce44277485f52af9b)
+++ kernel/generic/include/adt/list.h	(revision cd6287931f05186767f2ccee516423a0342dfad2)
@@ -38,6 +38,9 @@
 
 #include <assert.h>
+#include <macros.h>
+#include <member.h>
 #include <stdbool.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <trace.h>
 
@@ -89,8 +92,8 @@
 
 #define list_get_instance(link, type, member) \
-	((type *) (((void *)(link)) - list_link_to_void(&(((type *) NULL)->member))))
+	member_to_inst(link, type, member)
 
 #define list_foreach(list, member, itype, iterator) \
-	for (itype *iterator = NULL; iterator == NULL; iterator = (itype *) 1) \
+	for (itype *iterator = NULL; iterator == NULL; iterator = &((itype *) NULL)[1]) \
 		for (link_t *_link = (list).head.next; \
 		    iterator = list_get_instance(_link, itype, member), \
@@ -98,5 +101,5 @@
 
 #define list_foreach_rev(list, member, itype, iterator) \
-	for (itype *iterator = NULL; iterator == NULL; iterator = (itype *) 1) \
+	for (itype *iterator = NULL; iterator == NULL; iterator = &((itype *) NULL)[1]) \
 		for (link_t *_link = (list).head.prev; \
 		    iterator = list_get_instance(_link, itype, member), \
@@ -375,7 +378,7 @@
  *
  */
-static inline link_t *list_nth(const list_t *list, unsigned long n)
-{
-	unsigned long cnt = 0;
+static inline link_t *list_nth(const list_t *list, size_t n)
+{
+	size_t cnt = 0;
 
 	link_t *link = list_first(list);
@@ -391,13 +394,4 @@
 }
 
-/** Verify that argument type is a pointer to link_t (at compile time).
- *
- * This can be used to check argument type in a macro.
- */
-static inline const void *list_link_to_void(const link_t *link)
-{
-	return link;
-}
-
 /** Determine if link is used.
  *
Index: kernel/generic/include/adt/odict.h
===================================================================
--- kernel/generic/include/adt/odict.h	(revision e037cf3733f322897cbfc63ce44277485f52af9b)
+++ kernel/generic/include/adt/odict.h	(revision cd6287931f05186767f2ccee516423a0342dfad2)
@@ -37,4 +37,5 @@
 
 #include <errno.h>
+#include <member.h>
 #include <stdbool.h>
 #include <stddef.h>
@@ -42,5 +43,5 @@
 
 #define odict_get_instance(odlink, type, member) \
-	((type *)( (void *)(odlink) - ((void *) &((type *) NULL)->member)))
+	member_to_inst(odlink, type, member)
 
 extern void odict_initialize(odict_t *, odgetkey_t, odcmp_t);
Index: kernel/generic/include/macros.h
===================================================================
--- kernel/generic/include/macros.h	(revision e037cf3733f322897cbfc63ce44277485f52af9b)
+++ kernel/generic/include/macros.h	(revision cd6287931f05186767f2ccee516423a0342dfad2)
@@ -160,8 +160,4 @@
 	})
 
-#define member_to_inst(ptr_member, type, member_identif) \
-	((type *) (((void *) (ptr_member)) - \
-	    ((void *) &(((type *) 0)->member_identif))))
-
 /** Get the size of an array in array elements
  *
Index: kernel/generic/include/member.h
===================================================================
--- kernel/generic/include/member.h	(revision cd6287931f05186767f2ccee516423a0342dfad2)
+++ kernel/generic/include/member.h	(revision cd6287931f05186767f2ccee516423a0342dfad2)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kernel_generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_MEMBER_H_
+#define KERN_MEMBER_H_
+
+#include <stdint.h>
+
+#define member_to_inst(ptr_member, type, member_identif) \
+	((type *) (((uintptr_t) (ptr_member)) - \
+	    offsetof(type, member_identif)))
+
+#endif
+
+/** @}
+ */
