不能直接用 static_cast 将 long 转为指针,因为 c++ 类型安全机制禁止整数与指针间的直接转换,防止因非法地址解引用导致段错误;应使用 reinterpret_cast 配合 intptr_t 和显式检查。

为什么不能直接用 static_cast 把 long 转成指针
因为 static_cast 不允许在整数和指针之间做隐式或直接转换,编译器会报错:error: cannot convert 'long int' to 'void*' in initialization。这不是语法限制,而是 C++ 类型安全机制在拦截潜在危险操作——比如把一个随机数值当地址去解引用,大概率导致段错误或未定义行为。
常见错误场景包括:从系统 API(如 Windows 的 LPARAM、X11 的 XEvent 成员)里拿到一个整型句柄,误以为能直接转成对象指针;或试图复用旧 C 风格的“万能整数传参”模式。
正确做法:用 reinterpret_cast + 显式对齐和大小检查
reinterpret_cast 是唯一被标准允许用于整数/指针双向转换的 cast,但它不负责验证合法性——你得自己确保:long 的值确实是某个有效对象的地址,且该地址在当前平台能被 long 完整容纳。
- 在 64 位 Linux/macOS 上,
long通常是 64 位,和指针宽度一致;但在 Windows 64 位下,long仍是 32 位,此时直接转会截断高位,必须改用long long或intptr_t - 推荐优先使用
intptr_t(定义在<cstdint></cstdint>),它是专门设计来无损承载指针的整数类型 - 转换前建议加断言:
assert(reinterpret_cast<void>(addr) != nullptr);</void>,避免空指针误用
示例:
#include <cstdint> void* ptr = reinterpret_cast<void>(static_cast<intptr_t>(addr)); // 反向转换同理: intptr_t addr = reinterpret_cast<intptr_t>(ptr); </intptr_t></intptr_t></void></cstdint>
用 std::bit_cast(C++20)替代裸 cast 的前提条件
std::bit_cast 更安全,但要求源和目标类型大小严格相等,且都 trivially copyable。对 long → 指针来说,它只在 sizeof(long) == sizeof(void*) 时可用,否则编译失败。
- 不能用于
long到MyClass*的直接转换,必须先到void*再static_cast - 比
reinterpret_cast多一层编译期检查,适合新项目或明确控制平台的场景 - 如果目标平台不确定,仍应回退到
intptr_t+reinterpret_cast
示例:
#include <bit> void* p = std::bit_cast<void>(addr); // addr 必须是 intptr_t 或等宽整型 </void></bit>
实际项目中更稳妥的封装方式
裸 cast 容易漏掉平台差异和生命周期检查。真实项目里应封装为带语义的工具函数,例如:
- 用
uintptr_t替代long存储地址——无符号、保证与指针同宽 - 转换函数内嵌
static_assert(sizeof(uintptr_t) == sizeof(void*), "pointer/integer size mismatch"); - 若该
long来自外部(如 DLL 回调参数),务必确认其来源是否真的代表有效内存地址,而非 ID 或标志位
别忘了:地址有效性无法靠类型系统保证,运行时仍需配合 if (ptr) { ... } 或 mmap/页保护等手段做防御性检查。
真正麻烦的从来不是怎么转,而是怎么确认那个数字确实是个活地址——这一步没人能替你做。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











