C语言中的字符串常量和字符数组对比

3

可能是重复问题:
C语言中char s[]和char *s有什么区别?

这更像是一个普遍性的问题,而不是试图修复某个问题。我一直在阅读C编程语言书籍,他们特别强调了以下两者之间的区别:

char amessage[] = "blah";
char *pmessage = "blah";

两者之间的区别在于一个是字符数组,另一个是指向字符串常量的指针。他们说修改字符数组是可以接受的,但你不应该修改字符串常量,因为这会触发未定义的行为。我的问题是:难道字符串常量不是以与字符数组相同的方式存储在内存中吗?为什么我可以像这样修改它:

char *p = "this is a string constant";
*(p+2) = 'a';
printf("%s", p);

最终打印结果为“thas is a string constant”,正如你所预期的那样。我可以理解,在运行时更改字符串常量可能会使其他人/您混淆,他们/您可能不希望其值发生变化,但从纯功能角度来看,有什么问题?可能触发哪些未定义的行为?当字符数组无法胜任时,它可能如何产生反作用?我只是想知道是否我对内存中字符串常量的工作方式及编译器如何看待它们有所遗漏。
3个回答

4

至少在我的电脑上,以下程序会崩溃:

#include <stdio.h>
int main() { 
  char *p = "this is a string constant";
  *(p+2) = 'a';
  printf("%s", p);
}

如果它对你起作用(在某些嵌入式编译器上可能会),那只是你运气好。未定义的行为意味着程序可以做任何事情。请参见http://blog.regehr.org/archives/213
另请参阅char s[]和char *s之间有什么区别?

我使用的是vc2010。感谢您找到了另一个问题,当我搜索时没有看到它:D - ameer
大多数嵌入式编译器将字符串文字存储在真正的ROM中,因此它们不太可能允许修改。而基于RAM的系统(如DOS)的旧编译器更有可能允许此操作。 - Lundin

1

对于字符数组而言,字符串字面量"blah"的内容也会被复制到堆栈上。因此,您可以修改它而不会引发未定义行为,因为毕竟它只是一份副本。

对于char *而言,您实际上是在尝试修改原始的字符串字面量,根据标准,这是未定义行为。


0

使用字符串常量时,数据存储的位置是不确定的 -- 编译器可以自由地进行任何技巧,因为你应该被禁止写入它。例如,指针实际上可能指向加载的可执行代码本身中定义字符串常量的位置。


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