为什么char*能修改指向只读内存的字符串字面量?
关于你的问题可以从以下几个层面解释:
1. 为什么char* p = "hello"仅得到警告而能编译通过
这是C为了兼容C语言遗留代码做的妥协。早期C标准中字符串字面量的类型是char[N],没有const限定,大量旧代码都直接用非const的char*指向字符串字面量。C标准后续虽然明确字符串字面量是const char[N]类型,但为了避免海量旧代码直接编译失败,长期允许这种不安全的隐式类型转换,仅要求编译器给出警告。直到C++11标准正式将这个隐式转换列为废弃特性,高版本编译器如果指定-std=c++11及以上的严格编译标准,会直接对这行代码报错。
2. 为什么部分场景下修改字符串字面量不会被操作系统拦截
你观察到修改p[0]后能输出yello,本质是你的编译器默认配置没有把字符串字面量放到只读内存段,分两种常见情况:
- 部分老旧编译器、嵌入式平台编译器默认不会开启字符串字面量只读保护,会把所有字符串字面量放到可读写的数据段,这种场景下修改当然不会被拦截,但属于依赖编译器实现的未定义行为,换个编译环境就会失效。
- 主流桌面系统的现代编译器(比如GCC、Clang)默认会把字符串字面量放到只读的
.rodata段,这种场景下你修改p[0]会直接触发操作系统的内存保护机制,抛出段错误直接终止程序,根本不会有输出。你遇到的可运行情况只是特定编译配置下的特例。
3. 你对char arr[] = "hello"的认知完全正确
这行代码确实会在栈上分配长度等于字符串字面量长度+1(末尾补\0)的数组空间,将字符串字面量的内容完整拷贝到栈内存中,栈内存本身是可读写的,对数组元素的修改是完全合法的、行为确定的操作。
内容的提问来源于stack exchange,提问作者Karen Baghdasaryan
相关产品推荐
相关产品推荐

