C++中char* str1 = "Hello world"的字符串与指针存储位置查询
解答
你需要先拆分两个完全独立的存储对象:指针str1本身,以及它指向的字符串字面量"Hello world",二者的存储区域并不相同:
- 指针
str1的存储位置和它的声明作用域直接相关:如果这行代码定义在函数内部,它属于局部变量,存储在栈上;如果定义在函数外部作为全局变量,它会存储在全局/静态存储区。 - 你调试时发现既不在堆也不在栈上的是
"Hello world"字符串本身,它存储在进程地址空间的只读数据段(.rodata 段),属于程序静态存储区的一部分。这块区域的内容是编译器在编译阶段就写入可执行文件的,程序启动加载时由操作系统直接映射到内存,不需要你在代码中手动申请分配,所以你可以直接通过指针读取到字符串内容。
你教授的说法和实际运行效果并不矛盾:
你教授提到的「没有为str1分配可指向的内存」,实际指的是你没有主动分配可写的内存给str1指向:.rodata 段的内存属性是只读的,如果你尝试通过
str1修改字符串中的字符(比如执行str1[0] = 'h'),会直接触发段错误导致程序崩溃。C++标准把char*直接指向字符串字面量的写法标记为弃用,本质就是为了避免开发者误以为这段内存可写,引发无预警的运行时错误。符合规范的写法应该是const char* str1 = "Hello world";,从语法层面就禁止对指向内容的修改操作。
如果你想自行验证变量的内存位置,在Linux环境下可以通过以下方法操作:
- 打印不同存储类型变量的地址对比,参考测试代码:
#include <iostream> #include <cstdlib> using namespace std; int global_test_var; int main() { int stack_test_var; int* heap_test_var = new int; const char* str_test = "Hello world"; cout << "全局变量地址:" << &global_test_var << endl; cout << "栈局部变量地址:" << &stack_test_var << endl; cout << "堆变量地址:" << heap_test_var << endl; cout << "字符串字面量地址:" << (void*)str_test << endl; cout << "指针str_test本身的地址:" << &str_test << endl; delete heap_test_var; return 0; }
运行后你可以直观看到,字符串字面量的地址和全局变量的地址区间接近,和栈、堆的地址区间都有明显差异。
2. 编译得到可执行文件后,执行readelf -S 你的可执行文件名命令查看段信息,可以直接看到.rodata段的地址范围,和你打印的字符串字面量地址完全匹配。
内容的提问来源于stack exchange,提问作者JAYD3V
相关产品推荐
相关产品推荐

