指针的数字值
使用 reinterpret_cast
将指针转换为整数的结果是实现定义的,但“……对于那些知道底层机器的寻址结构的人来说,意图是不足为奇的。”
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
同样,通过从整数转换获得的指针也是实现定义的。
将指针存储为整数的正确方法是使用 uintptr_t
或 intptr_t
类型:
// `uintptr_t` was not in C++03. It's in C99, in <stdint.h>, as an optional type
#include <stdint.h>
uintptr_t uip;
Version >= C++ 11
// There is an optional `std::uintptr_t` in C++11
#include <cstdint>
std::uintptr_t uip;
对于定义 uintptr_t
(C99 标准,6.3.2.3),C++ 11 引用 C99:
一个无符号整数类型,其属性是任何到
void
的有效指针都可以转换为这种类型,然后转换回指向void
的指针,结果将等于原始指针。
同时,为广大现代的平台上,你可以假设一个平面地址空间和 uintptr_t
算术相当于对 char *
算术,这是完全有可能实现转换 void *
到 uintptr_t
只要改造时进行任何改造可以逆转从 uintptr_t
回到 void *
时。
技术性
-
在符合 XSI 的(X / Open System Interfaces)系统上,需要
intptr_t
和uintptr_t
类型,否则它们是可选的。 -
在 C 标准的含义内,函数不是对象; C 标准不保证
uintptr_t
可以保存一个函数指针。无论如何,POSIX(2.12.3)
一致性要求:所有函数指针类型应与 void 指向的类型指针具有相同的表示形式。将函数指针转换为 void *不得改变表示。这种转换产生的 void *值可以使用显式转换转换回原始函数指针类型,而不会丢失信息。
-
C99§7.18.1:
当 typedef 名称仅在缺少或存在初始 u 时定义时,它们应表示 6.2.5 中描述的相应的有符号和无符号类型; 提供这些相应类型之一的实现也应提供另一种。
uintptr_t
可能是有意义的,如果你想对指针的位做一些你不能用有符号整数明智地做的事情。