Numeric value of a pointer
suggest changeThe 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 to void, 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
anduintptr_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.