intptr_t
is a new invention, created after 64-bit and even 128-bit memory addresses were imagined.
If you ever need to cast a pointer into an integer type, always use intptr_t
. Doing anything else will cause unnecessary problems for people who need to port your code in the future.
It took a long time to iron out all of the bugs with this in programs like Mozilla/Firefox when people wanted to compile it on 64-bit Linux.
It is mostly a stylistic argument (an optimizing compiler would probably generate the same, or very similar, code). However, pointer compares may be a tricky issue.
Remember than in purely standard C pointer compare is roughly meaningful only for pointers to the same aggregate data. You are probably not allowed to compare two results from malloc
, e.g. to keep a sorted array of pointers.
I would keep them as void*
, or else as uintptr_t
. The signed intptr_t
has the inconvenience to seggregate negative and positive numbers, and where they are coming from significant application pointers, this is probably not welcome.
Notice that a void*
cannot be dereferenced: as an uintptr_t
, you have to cast it to do something useful with the data pointed by the address; however void*
pointers can be passed to routines like memset
PS. I am assuming an ordinary processor (e.g. some x86, PowerPC, ARM, ...) with a flat virtual address space. You could find exotic processors -some DSPs perhaps- with very significant differences (and perhaps on which intptr_t
is not always meaningful; remember that on the 1990s Cray Y-MP supercomputers sizeof(long*) != sizeof(char*)
; at that time C99 did not exist, and I am not sure its <stdint.h>
could be meaningful on such machines)
Best Answer
No.
intptr_t
is not guaranteed to exist. First, as you note, it was introduced in C99. Second, implementations are not required to have an integer type big enough to hold converted pointer values without loss of information.Converting an
int
tointptr_t
and back is unlikely to lose information but there's no actual guarantee thatintptr_t
is wider thanint
.If you want to store pointer values, store them in pointer objects. That's what pointer objects are for.
Any pointer to an object or incomplete type can be converted to
void*
and back again without loss of information. There is no such guarantee for pointers to functions -- but any pointer-to-function type can be converted to any other pointer-to-function-type and back without loss of information. (I'm referring to the C standard; I think POSIX provides some additional guarantees.)If you want to store either an integer or a pointer value in the same object, the first thing you should do is re-think your design. If you've already done so, and concluded that you really do want to do this, consider using a union (and keeping careful track of what kind of value you've stored most recently).
There are APIs that use a
void*
argument to allow arbitrary data to be passed; see, for example, the POSIXpthread_create()
function. This can be abused by casting an integer value tovoid*
but it's safer to pass the address of an integer object.