为什么C++中cout输出&"hello"会得到随机内存地址,原理是什么?
现象原因与底层原理解释
你看到的输出是字符串字面量"hello"在当前进程虚拟地址空间中的存储地址,底层是C++类型规则、运算符重载机制和操作系统内存布局共同作用的结果:
- 首先明确字符串字面量的类型与存储:
"hello"在C++中是*const char[6]*类型的常量(末尾隐含'\0'所以长度是6),程序编译后会被存入二进制文件的只读数据段(.rodata),程序运行时操作系统会把这个段加载到进程的虚拟地址空间中,这段内存的起始地址就是你输出的0x开头的十六进制数值。 - 其次是取地址操作的类型结果:
&"hello"是对数组类型的字符串字面量取地址,得到的是const char (*)[6]类型的数组指针,也就是指向长度为6的const char数组的指针。 - 最后是
std::cout的重载匹配逻辑:std::ostream的operator<<仅对const char*类型做了特殊处理,会输出指针指向位置到'\0'为止的字符串内容;除const char*外的所有指针类型,都会匹配到operator<<(const void*)重载,这个重载的功能就是直接输出指针存储的内存地址值。
你看到的地址每次运行都会变化是因为操作系统默认开启了*地址空间布局随机化(ASLR)*安全机制,每次程序启动时各个内存段的加载基址都会被随机偏移,避免攻击者利用固定内存地址发起攻击。
你可以做两个简单验证:
- 把
cout<<&"hello";改为cout<<"hello";,此时数组会隐式转换为指向首元素的const char*,会直接输出hello字符串 - 把
cout<<&"hello";改为cout<<(const void*)"hello";,输出的地址和你现有代码的输出结果完全一致,因为字符串字面量本身的地址和它首元素的地址数值是相等的,只是类型不同。
内容的提问来源于stack exchange,提问作者John Mellow
相关产品推荐
相关产品推荐

