C++学习------字符串字面量(string literal)
·
- 操作系统:ubuntu22.04
- IDE:Visual Studio Code
- 编程语言:C++11
C/C++ 中 字符串字面量(string literal) 在不同上下文中的内存属性差异。下面我们从修改内容的角度详细解释两者的区别:
✅ 代码
char a[] = "hello"; // (1) 数组初始化
a[0] = 'X'; // ✅ 合法:可以修改
char *p = "world"; // (2) 指针指向字符串字面量
p[0] = 'X'; // ❌ 非法:修改只读内存 → 运行时崩溃(如 Segmentation Fault)
一、根本区别:内存存储位置与可写性
| 表达式 | 内存分配位置 | 是否可修改 | 原因 |
|---|---|---|---|
char a[] = "hello"; |
栈(stack) | ✅ 可修改 | 编译器将 "hello" 复制一份到栈上,a 是一个可写的字符数组 |
char *p = "world"; |
只读数据段(.rodata) | ❌ 不可修改 | "world" 存储在程序的只读内存区,p 只是指向它的一个指针 |
二、深入解析
1. char a[] = "hello";
- 这是一个数组定义 + 初始化。
- 编译器行为:
- 在栈上分配 6 字节空间(5个字符 +
\0); - 将字符串字面量
"hello"的内容逐字节拷贝到这个栈空间;
- 在栈上分配 6 字节空间(5个字符 +
- 结果:
a是一个可读可写的局部数组,修改a[0]完全合法。
🔍 内存示意图:
栈区: a: ['h', 'e', 'l', 'l', 'o', '\0'] ← 可修改
2. char *p = "world";
- 这是一个指针变量初始化。
- 编译器行为:
- 将字符串字面量
"world"存入只读数据段(.rodata); p被赋值为该字符串的地址;
- 将字符串字面量
- 结果:
p指向的是只读内存,任何尝试修改的行为都会导致未定义行为(Undefined Behavior),通常表现为 Segmentation Fault。
🔍 内存示意图:
.rodata 段(只读): "world\0" ← 程序加载时写入,运行时不可改 栈区: p: ────────→ 指向 .rodata 中的 "world"
三、为什么编译器不报错?
- C/C++ 标准允许将字符串字面量赋给
char*(出于历史兼容性),但现代编译器会警告。 - 例如,用
gcc -Wall编译:warning: deprecated conversion from string constant to ‘char*’ - C++11 起已禁止:在 C++ 中,
char *p = "world";是编译错误,必须写成const char *p = "world";。
✅ 正确且安全的写法(C 和 C++ 通用):
const char *p = "world"; // 明确表示指向常量
// p[0] = 'X'; // 编译器直接报错!
四、总结对比表
| 特性 | char a[] = "hello"; |
char *p = "world"; |
|---|---|---|
| 类型 | char[6](数组) |
char*(指针) |
| 内存位置 | 栈(可写) | .rodata(只读) |
| 内容来源 | 复制字符串字面量 | 直接指向字面量 |
| 能否修改内容 | ✅ 能 | ❌ 不能(运行时错误) |
| 编译器检查 | 修改合法 | 修改不报错(但应警告) |
| 推荐写法 | 无问题 | 应写为 const char *p = "world"; |
💡 最佳实践建议
- 永远不要试图修改字符串字面量;
- 在 C++ 中,始终用
const char*指向字符串字面量; - 在 C 中,也应主动加
const提高安全性; - 如果需要可修改的字符串,要么用数组,要么动态分配:
char *p = malloc(6); strcpy(p, "hello"); p[0] = 'X'; // ✅ 安全 free(p);
🌟 记住:
“能通过编译” ≠ “能安全运行”。
字符串字面量是常量,尊重它的只读属性,是写出健壮 C/C++ 程序的关键一步。
更多推荐


所有评论(0)