用 std::cout 直接打印指针地址:std::cout
printf 或 std::cout 打印指针地址直接用 std::cout 会输出地址(格式为十六进制,无前缀),但容易被误认为是整数;用 printf 则必须匹配正确格式符,否则行为未定义。C++ 标准规定:打印指针地址应使用 %p,且参数需转为 void*。
常见错误:printf("%x", ptr) —— 这是错的,%x 期待 unsigned int,而指针大小在 64 位系统上通常是 8 字节,导致截断或崩溃。
printf("%p", static_cast(ptr)) 是安全写法,static_cast 显式转换,避免隐式转换警告std::cout 默认输出
地址,但不带 0x 前缀;加 std::hex 可模拟 %p 风格:std::cout (ptr)nullptr)做解引用或非法转换,但打印 static_cast(nullptr) 是合法的void* 是打印指针的“中间标准”因为 void* 是唯一能隐式接收任意对象指针类型的指针类型(函数指针除外),且 %p 要求的就是 void*。其他类型如 int*、char* 不能直接传给 %p,编译器可能警告(如 GCC 的 -Wformat),运行时也可能出问题(尤其在 Windows + MSVC 下)。
char* 是特例:它常被当作字符串处理,printf("%p", str) 若没转 void*,可能意外触发字符串打印逻辑(取决于实现)reinterpret_cast(ptr) 和 static_cast(ptr) 在对象指针场景下等价,但 static_cast 更语义准确、更易被静态分析工具识别void*(C++ 标准禁止),调试时需用平台特定方法(如 printf("%p", (void*)func_ptr) 在多数平台可行但非标准)(optimized out)
如果用 GDB 或 IDE 调试时看到指针值显示为 (optimized out),不是打印方式的问题,而是编译器优化导致变量未实际存入寄存器或栈。此时即使你写了正确的 printf,运行时也可能拿到垃圾值或崩溃。
-O0 关闭优化,配合 -g 保留调试信息asm volatile("" :: "r"(ptr));,让编译器认为该变量被“使用”%p 输出带 00000000`XXXXXXXX 格式怎么办这是 Windows CRT 对 %p 的默认行为(用反引号分隔高低 32 位),符合 Win64 ABI,但和 Linux 的纯十六进制不一致。若需统一格式(比如日志比对),不能依赖 %p 直接输出。
std::ostringstream + std::hex + std::setw(16) + std::setfill('0') 手动格式化:std::hex (ptr)
uintptr_t(定义在 )而非 size_t,它是专为指针整数转换设计的无符号类型,可移植性更好long 或 unsigned long —— 它们在 Windows 64 位下仍是 4 字节,会截断地址