不能直接用 int 强转指针,因为在 64 位系统上 int 通常仅 4 字节,而指针为 8 字节,会导致高位截断、数据丢失和未定义行为;应使用 uintptr_t 进行安全可移植的转换,并注意生命周期、对齐及序列化设计。

为什么不能直接用 int 强转指针
直接写 (int)ptr 或 static_cast<int>(ptr)</int> 在 64 位系统上会截断地址高位,导致数据丢失和未定义行为。指针宽度通常是平台相关的(x86_64 下为 8 字节),而 int 往往只有 4 字节,这种转换既不安全也不可移植。
应该用 uintptr_t 而不是 long
uintptr_t 是 C++11 引入的标准无符号整数类型,保证能容纳任意对象指针的值。它比 long 更可靠,因为 long 在 Windows x64 上仍是 4 字节(LLP64),而 uintptr_t 在所有主流平台都匹配指针宽度。
实操建议:
- 包含头文件:
#include <cstdint></cstdint> - 转换写法:
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);</uintptr_t> - 反向还原必须用
reinterpret_cast,且原始指针类型需明确:int* p = reinterpret_cast<int>(addr);</int> - 不要用
static_cast替代reinterpret_cast—— 编译器会拒绝或静默出错
在 printf / cout 中打印指针整数值要注意格式符
用 printf 打印 uintptr_t 时,不能用 %d 或 %lx 硬编码——它们依赖平台 ABI。正确做法是:
- C 风格:
printf("0x%" PRIXPTR, addr);(需#include <inttypes.h></inttypes.h>) - C++ 风格:
std::cout (注意:不带 <code>0x前缀,也不保证大小写) - 若需固定宽度和前缀,推荐:
std::cout
跨线程/跨模块传递指针整数时容易忽略对齐和生命周期
把指针转成 uintptr_t 后存到日志、网络包或共享内存里,不代表它还能安全还原使用。常见陷阱:
- 原始对象已被
delete或离开作用域 → 还原后解引用即崩溃 - 指针来自
new[]或特定对齐分配(如aligned_alloc),但整数本身不携带对齐信息 - 在不同 DLL/so 间传递时,若原始指针指向模块内部静态数据,加载基址变化可能导致地址失效
- 某些嵌入式平台或启用 Control Flow Integrity(CFI)时,指针值可能被混淆,直接转整数会破坏验证逻辑
真正需要“序列化指针”的场景,通常该换设计:用句柄表、ID 映射或智能指针管理生命周期,而不是裸地址转整数。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











