Given the requirement that I need to store the value of a \"generic\" pointer in a struct and have no interest in the pointed-at memory itself, I find it more semantically corre
You should pick the type appropriate for the given system and program. Most of the time, pointers are positive address values, in which case uintptr_t
is the correct type. But some systems use negative addresses as a way to express kernel space, as explained here: Can a pointer (address) ever be negative? This would be the reason why there are two different types.
As for (u)intptr_t
vs void*
for a generic pointer type, the former is preferred in rugged, professional programs. There are many problems/bug sources associated with pointer types:
const
, which makes pointer conversions to/from that type questionable or poorly-defined.void*
and other pointer types happen implicitly, making it easy for bugs related to using the wrong pointer type to slip through unnoticed. This was fixed in C++, but remains a hazard in C. Take for example the old but classic "I forgot to include stdlib.h while using malloc in C90" bug.void*
. Doing so relies on non-standard compiler extensions.That being said, a whole lot of legacy code relies on void
pointers, and it's perfectly fine to use them in a restricted context. Some examples would be canonical code relying on generic callback functions: bsearch
, qsort
, pthreads and similar.
I would however not recommend to use void
pointers when designing new C programs - they are, in my opinion, best regarded as a dangerous feature of the past. There exist better and safer methods of generic C programming nowadays, such as C11 _Generic
, tricks using designated initializers, passing parameters as array pointers (to VLA), bounds-checking at compile time with static_assert
etc. Some examples can be found in my answer here: How to create type safe enums?.