字符串字面量存于只读内存,char 指向它虽语法合法但修改会导致未定义行为(如崩溃);应声明为 const char 或使用 std::string/栈数组等可写副本。

char* 指向字符串字面量时为什么不能修改
因为字符串字面量(如 "hello")在 C++ 中存储在只读内存段,用 char* 指向它语法合法,但后续若尝试修改内容(比如 p[0] = 'H'),行为是未定义的——多数情况下直接崩溃或被操作系统拦截。
常见错误现象:Segmentation fault、EXC_BAD_ACCESS,尤其在 macOS/Linux 下更敏感。
- 正确做法是声明为
const char*,编译器会阻止赋值操作 - 如果真需要修改,必须把字符串复制到可写内存,例如用
std::string或堆/栈数组 - 注意:C++11 起,
char* p = "hello";已是废弃写法(deprecated),编译器通常会警告
const char* 和 char const* 有区别吗
没有实质区别,两者都等价于“指向 const char 的指针”,const 修饰紧邻的类型左侧(char),所以 const char* 和 char const* 完全等效。
但容易混淆的是 char* const p:这是“const 指针”,指针本身不可变(不能指向别处),但所指内容可改——这和字符串常量场景不匹配,别误用。
- 推荐统一写
const char*,符合主流阅读习惯 - 用
auto推导时,auto p = "hello";在 C++14 后推导为const char*,安全
想修改字符串内容,该用什么替代方案
直接对字符串字面量取地址后修改是危险且不可靠的。可靠路径只有两条:复制到可写空间,或用更高层抽象。
-
std::string s = "hello";—— 内容可自由修改,底层自动管理内存 -
char buf[] = "hello";—— 在栈上创建可写副本,buf是数组名,不是指针常量 -
char* p = new char[6]{"hello"};—— 手动堆分配,记得delete[] p; - 避免
char* p = strdup("hello");(C 风格),C++ 中优先用std::string或std::vector<char></char>
函数参数里接收字符串常量该怎么声明
所有接受字符串字面量的函数参数,只要不修改内容,就应声明为 const char*。这是接口契约:你承诺不碰数据,调用方才敢放心传 "abc"。
反例:void f(char* s) 会导致 f("abc") 编译失败(C++11 起)或触发警告;而 void f(const char* s) 可安全接收字面量、std::string.c_str()、甚至 nullptr(需自行判空)。
- 若函数内部要修改字符串,不要试图绕过
const强转(如const_cast),那只是把未定义行为延迟到运行时 - C++20 起可考虑用
std::string_view替代const char*,更安全且支持非 null-terminated 字符串
实际编码中,最常被忽略的是:即使你没写修改语句,某些看似无害的操作(比如传给一个声明为 char* 的旧 C 库函数)也会悄悄触发未定义行为。盯住类型,比盯住内容更重要。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











