为什么 char* 会导致未定义行为,而 char[] 不会呢?

10

尝试修改字符串常量会导致未定义的行为:

char * p = "wikipedia"; 
p[0] = 'W'; // undefined behaviour

防止这种情况的一种方法是将其定义为一个数组而不是一个指针:

char p[] = "wikipedia"; 
p[0] = 'W'; // ok

为什么使用char*会导致未定义行为,而使用char[]则不会呢?


3
这是一个问题,还是你在发布一些评论? - Marc B
问题就在于问题本身 :-) 我同意它的展示有些随意,但是嘿... - Kerrek SB
我已经投票支持重新开放这个问题。问题在标题中已经被编辑,现在在正文中。尽管可能是重复的问题,但我认为还是应该重新开放。 - Keith Thompson
1个回答

16
任何对C字符串常量的修改都具有未定义的行为。编译器可能会将字符串常量存储在只读内存中(由操作系统保护,除非你在嵌入式系统上),但语言并不要求这样做。作为程序员,你需要正确处理它。
一个足够聪明的编译器可以提示你应该将指针声明为:
const char * p = "wikimedia";

尽管在C语言中,没有使用const的声明是合法的(为了不破坏旧代码)。但无论是否有编译器警告,使用const都是一个非常好的主意。
(在C++中,规则是不同的;与C字符串字面值不同,C++字符串字面值确实是const。)
当您使用字面量初始化数组时,字面量本身仍然存在于程序映像的潜在只读区域,但它被复制到本地数组中:
char s[] = "wikimedia"; /* initializes the array with the bytes from the string */
char t[] = { 'w', 'i', ... 'a', 0 };  /* same thing */

请注意,char u[] = *p 不起作用——数组只能从大括号初始化器中初始化,而 char 数组还可以从字符串字面量中初始化。

任何自重的程序员都会考虑const正确性 ;) ... +1 - 0xC0000022L
@Complicatedseebio:基于你不被允许改变内容的前提下 :-) (这就是警告的用途。) - Kerrek SB
+1 对于像我这样的C++新手非常有帮助。我从来不知道我应该在char*之前加上const。谢谢。 - Terry Li
然而,您可以将“foo”分配给char *变量。任何警告都是不受欢迎的。 - Pascal Cuoq
@Complicatedseebio:是的,它是允许的,因此它不是一个错误。但这是值得警告的事情。就像 if (n = 0) - Kerrek SB
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接