intptr_t and uintptr_t questionsAuthors: Jay Ghiron
Date: 2026-10-29
Submitted against: C23
Status: Open
This issue is about the following:
The following type designates a signed integer type, other than a bit-precise integer type, with the property that any valid pointer to
voidcan be converted to this type, then converted back to pointer tovoid, and the result will compare equal to the original pointer:
intptr_tThe following type designates an unsigned integer type, other than a bit-precise integer type, with the property that any valid pointer to
voidcan be converted to this type, then converted back to pointer tovoid, and the result will compare equal to the original pointer:
uintptr_tThese types are optional.
(C23 7.22.2.5 "Integer types capable of holding object pointers" paragraph 1.)
For the purposes of this issue, assume that the implementation
supports both intptr_t and uintptr_t. Issues relating to
provenance will not be discussed. If
N3914 is
accepted, all questions except the last would also be relevant for the
types intfuncptr_t and uintfuncptr_t when considering _Any_func*
instead of void* and function pointers instead of object pointers.
For the purposes of this paragraph, what is a valid pointer? Should null be considered a valid pointer here? For all further questions, assume that all pointers provided as arguments in the examples are valid for whatever definition is chosen.
Since this paragraph specifically considers void*, does this
guarantee not extend to other object pointer types? For example:
#include<stdint.h>
const void*foo(const void*p){
return(const void*)(uintptr_t)p;
}
char*bar(int*q){
return(char*)(uintptr_t)q;
}
Can an implementation give different results for these functions when compared to casting between pointer types directly?
Can multiple conversions of the same pointer to intptr_t or multiple
conversions of the same pointer to uintptr_t result in different
values? For example:
#include<stdint.h>
int baz(void*r){
return(uintptr_t)r==(uintptr_t)r;
}
Can this function ever return zero? One example of where it would be
useful to guarantee equivalent results is xor linked lists, however
niche those are. If multiple conversions to uintptr_t can result in
different values then iteration has to keep uintptr_t values rather
than pointers, because pointers could not reliably turn back into
uintptr_t values that could be used for iteration.
The descriptions of intptr_t and uintptr_t are done independently,
was it intended to not provide any guarantees when converting between
them? For example:
#include<stdint.h>
void*qux(void*s){
return(void*)(uintptr_t)(intptr_t)s;
}
Was it intended that this may be undefined?
There does not appear to be anything that specifically prohibits
converting an intptr_t value to void* or a uintptr_t value to
void* when in either case it would result in a pointer to or one
past an object that has had its lifetime end. Can it be inferred from
C23 6.2.4 that the result is undefined assuming the integer value was
not reused, or can the resulting pointer still be used in some limited
contexts?