C++中char*指针输出为字符串而非地址的底层原理疑问
测试代码与运行结果回顾
#include <iostream> using namespace std; int main() { const char* b="str"; cout << b << endl; cout << *b << endl; cout << &b << endl; cout << *(&b) << endl; return 0; }
运行输出:
str s 0x7ffdf39c27f0 str
输出逐行解释
核心前提:C++标准库的std::cout对char*/const char*类型做了<<运算符的特殊重载,默认将其视为C风格字符串的首地址,会从该地址开始逐字节读取内存直到遇到'\0'终止符后输出所有读取到的字符,而非直接输出指针存储的地址值。
cout << b << endl;:b存储的是字符串常量"str"的首字符地址,cout识别到char*类型后按C风格字符串规则输出,最终打印str。cout << *b << endl;:对指针b解引用,取到首地址处存储的第一个字符's',最终打印s。cout << &b << endl;:&b是取指针变量b本身的内存地址,指针变量本身存储在栈内存中,所以直接输出该地址的十六进制值0x7ffdf39c27f0。cout << *(&b) << endl;:&b是b的内存地址,对该地址解引用得到的就是b本身,也就是指向"str"首地址的char*,逻辑和第一行完全一致,最终打印str。
常见疑问解答
为什么char*直接输出不是地址
这是C++标准库为了兼容C风格字符串的使用习惯做的设计,std::ostream的<<运算符针对字符指针类型做了专属重载,优先按字符串输出。如果需要输出char*存储的地址值,只需要将其强制转换为void*类型即可,示例:cout << static_cast<void*>(b) << endl;,此时就会打印"str"字符串本身的首地址。
为什么b和("str")结果一致
字符串字面量"str"本身的类型是const char[4](包含末尾的隐式'\0'),在大多数使用场景下会隐式转换为指向首元素的const char*指针,对该指针解引用就是取首字符's',和*b的逻辑完全相同,所以结果一致。
替换为char b[]为什么输出一致
当你将代码修改为char b[] = "str"时,b是栈上分配的字符数组,本身存储了s/t/r/'\0'四个字符。数组名在传入cout时会隐式转换为指向数组首元素的char*指针,后续的解引用、取地址操作的表现和指针版本完全一致,所以输出结果相同。
内存结构说明
以64位系统为例,对应内存布局如下:
| 内存区域 | 存储内容 | 地址示例 |
|---|---|---|
| 只读数据段 | 's' 、't'、'r'、'\0'(字符串常量"str") | 0x00005555abcd0000 ~ 0x00005555abcd0003 |
| 栈区 | 指针变量b,存储的值为字符串常量首地址0x00005555abcd0000 | 0x7ffdf39c27f0(即你输出的&b的结果) |
学习资料推荐
- 书籍:《C++ Primer》第5版,重点阅读第三章(字符串、数组和指针)、第十四章(运算符重载)相关章节,能系统理解C++指针、数组、重载规则的底层逻辑。
- 内容方向:可自行搜索C++隐式类型转换、C风格字符串实现原理、
std::ostream运算符重载规则相关的技术内容深入学习。
内容的提问来源于stack exchange,提问作者tequila
相关产品推荐
相关产品推荐

