直接用 std::cout 可输出数据到标准输出流,需包含 头文件,使用时可链式调用操作符

直接用 std::cout 就能打印指针地址,但结果是否是你想要的十六进制——取决于你指的“十六进制”是哪种形式:是带 <code>0x 前缀的标准地址格式,还是纯数字、无前缀、可对齐、可参与日志拼接的十六进制字符串。这两者行为不同、适用场景不同,不能混用。
std::cout 输出指针时自动带 0x 前缀,但 char* 是例外
当你写 std::cout ,只要 <code>ptr 是非 char* 类型(比如 int*、void*、MyClass*),std::cout 会调用专有重载,输出类似 0x7ffeedb9a9ac 的格式——总是带 0x,右对齐,宽度由平台决定。
但 char* 是特例:它会被当作 C 字符串处理,输出内容而非地址。例如:
char s[] = "hi";<br>char* q = s;<br>std::cout hi,不是地址
要强制输出 char* 的地址,必须显式转成 void*:
std::cout (q);- 或更推荐:
std::cout (q);(语义更清晰)
printf("%p", ptr) 要求强制转 void*
%p 是唯一正统、跨平台安全的指针地址打印方式,但它要求参数必须是 void* 类型,否则行为未定义(尤其在 64 位系统上可能截断)。
常见错误写法:
-
printf("%p", ptr);——ptr是int*?不合法,编译可能过,运行可能错 -
printf("%p", (unsigned long)ptr);—— 错误类型,%p不匹配
正确写法只有一种:
printf("%p", static_cast<void>(ptr));</void>- 若需统一加
0x前缀(某些 libc 实现默认不加),用"%#p"
需要纯十六进制数字字符串?别用 cout 或 printf
如果你要的是不带 0x、不带空格、可拼接、可控制大小写的字符串(比如用于日志 ID、调试标记、哈希输入),std::cout 和 printf 都不合适。
正确做法是转成整数再格式化:
- 先用
uintptr_t拆解指针值:uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);</uintptr_t> - 再用
std::ostringstream+std::hex+std::setfill控制输出 - 或用
spdlog::to_hex(如果项目已集成 spdlog):它专为字节序列设计,但传入单个地址需先 memcpy 到数组
示例(标准库):
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);<br>std::ostringstream oss;<br>oss std::string hex_str = oss.str(); // 如 "00007ffeedb9a9ac"</uintptr_t>
十六进制地址位数和平台强相关
地址本身是整数,其位宽由指针大小决定:sizeof(void*) 是关键指标。
- 32 位系统:
sizeof(void*) == 4→ 地址最多 8 位十六进制(因为 4 字节 × 2 = 8 hex digits) - 64 位系统:
sizeof(void*) == 8→ 最多 16 位十六进制
不要硬编码 std::setw(16);应动态计算:std::setw(2 * sizeof(void*))。否则在 32 位环境会多补零,在嵌入式或 WASM 环境可能出错。
另外,%u、%x 打印指针是危险操作——它们把指针当普通整数,64 位下必然丢高 32 位,绝对禁止。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











