必须将指针显式转换为 void 再传给 printf 的 %p,否则是未定义行为;std::cout 自动输出指针地址,但 char 会被当作字符串打印而非地址。

用 printf 打印指针地址必须转成 void*
直接传 int*、char* 等非 void* 指针给 printf 的 %p 是未定义行为。C++ 标准要求 %p 只接受 void* 类型参数,否则可能崩溃、输出乱码或被编译器警告(如 GCC/Clang 的 -Wformat)。
-
printf("%p", ptr);—— 错误,ptr是int*或其它具体类型指针 -
printf("%p", (void*)ptr);—— 正确,显式转为void* - C++ 中推荐用
static_cast替代 C 风格强制转换,更安全且可被编译器检查(ptr)
std::cout 输出指针地址不需要手动转 void*
std::cout 对指针有专门重载:当操作数是任意对象指针(非 void*)时,它会自动以十六进制地址格式输出;但若是指向 char 的指针(char*),std::cout 会当作 C 字符串尝试打印内容,不是地址 —— 这是最大陷阱。
int x = 42; int* p = &x; std::cout → 输出类似0x7ffeedb9a9acchar s[] = "hi"; char* q = s; std::cout → 输出hi,不是地址- 要强制输出
char*地址:写成std::cout (q);
地址格式差异:printf 默认不带 0x 前缀,std::cout 默认带
这是实际调试时容易混淆的点。两者都输出十六进制,但前缀和对齐方式不同,不能靠肉眼比对是否相等。
-
printf("%p", ptr);→ 可能输出0x7ffeedb9a9ac(取决于平台和 libc 实现),有些系统输出无前缀的纯十六进制 std::cout → 总是带0x前缀,且默认右对齐,宽度由地址长度决定- 如需统一格式(比如日志对齐),
printf可用"%#p"强制加0x;std::cout需搭配std::hex、std::showbase和std::uintptr_t转换
跨平台安全起见,优先用 std::uintptr_t 转整数再输出
虽然 void* 足够应付大多数调试场景,但若需做算术(比如地址偏移)、存入容器或序列化,直接用指针类型仍有平台依赖风险(如某些嵌入式系统指针不是 64 位)。标准提供 std::uintptr_t —— 一个能容纳任意对象指针值的无符号整数类型。
立即学习“C++免费学习笔记(深入)”;
std::cout (ptr);-
printf("0x%" PRIxPTR, reinterpret_cast<:uintptr_t>(ptr));(需包含) - 注意:
reinterpret_cast是此处唯一合法的转换方式,static_cast不允许指针与整数互转
地址本身没有“类型含义”,但输出时的类型转换、重载选择和格式控制稍有偏差,就可能看到完全不同的字符串——尤其在混合使用 printf 和 std::cout、或处理 char 时,最容易漏掉那一次 static_cast。











