The result of casting a pointer to an integer using reinterpret_cast
is implementation-defined, but "... is intended to be unsurprising to those who know the addressing structure of the underlying machine."
int x = 42;
int* p = &x;
long addr = reinterpret_cast<long>(p);
std::cout << addr << "\n"; // prints some numeric address,
// probably in the architecture's native address format
Likewise, the pointer obtained by conversion from an integer is also implementation-defined.
The right way to store a pointer as an integer is using the uintptr_t
or intptr_t
types:
// `uintptr_t` was not in C++03. It's in C99, in <stdint.h>, as an optional type
#include <stdint.h>
uintptr_t uip;
// There is an optional `std::uintptr_t` in C++11
#include <cstdint>
std::uintptr_t uip;
C++11 refers to C99 for the definition uintptr_t
(C99 standard, 6.3.2.3):
an unsigned integer type with the property that any valid pointer to
void
can be converted to this type, then converted back to pointer tovoid
, and the result will compare equal to the original pointer.
While, for the majority of modern platforms, you can assume a flat address space and that arithmetic on uintptr_t
is equivalent to arithmetic on char *
, it's entirely possible for an implementation to perform any transformation when casting void *
to uintptr_t
as long the transformation can be reversed when casting back from uintptr_t
to void *
.
Technicalities
On XSI-conformant (X/Open System Interfaces) systems, intptr_t
and uintptr_t
types are required, otherwise they are optional.
Within the meaning of the C standard, functions aren't objects; it isn't guaranteed by the C standard that uintptr_t
can hold a function pointer. Anyway POSIX (2.12.3) conformance requires that:
All function pointer types shall have the same representation as the type pointer to void. Conversion of a function pointer to void * shall not alter the representation. A void * value resulting from such a conversion can be converted back to the original function pointer type, using an explicit cast, without loss of information.
C99 ยง7.18.1:
When typedef names differing only in the absence or presence of the initial u are defined, they shall denote corresponding signed and unsigned types as described in 6.2.5; an implementation providing one of these corresponding types shall also provide the other.
uintptr_t
might make sense if you want to do things to the bits of the pointer that you can't do as sensibly with a signed integer.