C++ Numeric value of a pointer


Example

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;
C++11
// 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 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.