<p>不安全,因字符串字面量存于只读内存,通过char arr[]修改内容会触发段错误;只读场景应使用const char arr[],需修改时须用二维数组或动态分配可写内存。</p>

char* arr[] = {"a", "b"} 这种写法到底安全吗
直接用字符串字面量初始化 char* 数组是合法的,但背后有隐含风险:所有字符串字面量都存放在只读内存段,任何试图通过数组元素修改内容的操作(比如 arr[0][0] = 'x')都会触发段错误。这不是语法问题,而是运行时未定义行为。
常见错误现象:Segmentation fault (core dumped) 出现在对 arr[i][j] 赋值之后;或者在某些编译器(如 MSVC)下看似正常,换到 Linux + GCC 就崩溃。
- 如果只需读取字符串,
char* arr[] = {"hello", "world"}完全可用 - 如果后续要修改内容,必须改用
char arr[][N]或动态分配内存 - 更现代、安全的做法是改用
std::vector<:string></:string>,避免裸指针管理
想让每个字符串都能修改,该怎么初始化
必须为每个字符串分配可写的内存空间。最常用的是二维字符数组,它在栈上分配连续可写内存:
char arr[][16] = {
"apple",
"banana",
"cherry"
};这里 [16] 是每行最大长度(含 \0),编译器自动推导行数。注意:不能写成 char arr[][] = {...},列数不可省略。
立即学习“C++免费学习笔记(深入)”;
另一种方式是手动堆分配(适合长度不确定或较大):
char* arr[3]; arr[0] = new char[10]; strcpy(arr[0], "cat"); arr[1] = new char[12]; strcpy(arr[1], "elephant"); // 记得最后 delete[] arr[i]
漏掉 delete[] 会导致内存泄漏;用错 delete(没加方括号)会引发未定义行为。
为什么 const char* arr[] 比 char* arr[] 更合适
绝大多数只读场景下,应该显式加上 const:
const char* arr[] = {"foo", "bar", "baz"};这不只是风格问题:它让编译器帮你拦截非法写操作,比如 arr[0][0] = 'F' 会直接报错 error: read-only variable is not assignable,比运行时报段错误更容易定位。
参数差异很关键:函数接收字符串数组时,应优先声明为 const char* const arr[](数组本身和元素指向的内容都不可变),或至少 const char* arr[](内容不可变)。
-
char* arr[]→ 允许修改字符串内容(危险) -
const char* arr[]→ 禁止修改字符串内容(推荐) -
char* const arr[]→ 禁止修改指针值(即不能让arr[0] = ...)
初始化为空或部分赋值时要注意什么
C++ 允许不完全初始化,未指定的元素会被零初始化:
char* arr[5] = {"a", "b"}; // arr[2], arr[3], arr[4] 全为 nullptr但这个 nullptr 是隐式的,不是字符串 ""。后续若直接调用 strlen(arr[3]) 会崩溃。安全做法是显式检查:
if (arr[i] != nullptr) {
len = strlen(arr[i]);
}另一个坑:混用字符串字面量和局部数组地址:
char* arr[2];
{
char tmp[] = "local";
arr[0] = tmp; // 错!tmp 出作用域后地址失效
}这种写法编译不报错,但运行时读到的是垃圾数据,极难调试。
真正容易被忽略的是:字符串字面量的生命周期贯穿整个程序,而局部数组、std::string::c_str() 返回的指针都不是。只要用了 char*,就得盯紧内存归属。


















