2

此代码在 MS Visual Studio 中的行为很奇怪:

char *s = "hello";
s[0] = 'a';
printf(s); 

在启用优化的发布版本中,它会忽略 s[0] = 'a' 并打印“hello”。如果没有优化或调试版本,它会因访问冲突而崩溃。
这种行为是否符合 C++ 标准?在我看来,编译器应该只允许对字符串文字的常量引用,即

const char *s = "hello";

编辑:我知道它为什么这样工作,我不明白为什么允许我对只读内存进行非常量引用。

4

6 回答 6

14

不,这不是编译器中的错误。当你写:

char* s = "hello";

字符串常量"hello"将放置在只读部分中,如果您尝试修改它,应该会生成异常。(操作系统异常,而不是 C++ 异常)。

要使其可写,您必须使用数组:

char s[] = { 'h', 'e', 'l', 'l', 'o', 0 };

或者,如果你真的需要一个指针,让它指向一个数组:

char _s[] = { 'h', 'e', 'l', 'l', 'o', 0 };
char* s = _s;

我可以理解您关于只允许使用字符串文字初始化 const 指针的观点,但我认为这会破坏很多现有代码。

于 2009-02-23T16:20:46.397 回答
7

首先允许此代码(而不是要求声明为 type char const*)的原因是向后兼容旧的 C 代码。

不过,大多数处于严格模式的现代编译器都会对上述代码发出警告!

于 2009-02-23T16:28:56.393 回答
3

我认为 C++ 编译器可以按照标准在只读内存页中分配字符串文字。

于 2009-02-23T16:19:24.000 回答
2

这是行不通的,因为 *s 指向一个字符串常量的内存地址,你不能改变它。

实际上,我有点惊讶您在使用优化编译时没有遇到访问冲突。

于 2009-02-23T16:20:59.923 回答
1
char *s = "foo";

是一匹狡猾的小马。它并没有告诉您这确实是一个只读字符串,而实际上它是。之所以如此,是因为您可以让您的同事编写另一个字符串,例如:

char *t = "foo";

现在,编译器在其最有用的情况下只会保留一份副本,而更改一份将意味着大量工作,只是为了让您和您的朋友满意。因此,它不会尝试这样做。这是您应该在标准中找到的内容。你猜怎么着,你在做什么调用UB。

也就是说,如果你按照自己的方式行事,就会破坏许多标准委员会的穷人负担不起的遗留代码。所以,你来了。

请记住,const我们对无忧无虑的使用感到内疚不是一天产生的。Bjarne 做了很多反省,很多其他人也这样做了,不管是否把它放进去。事实上,他有一个很好的主意,即拥有只读和只写变量……但我会把这个故事留到另一天。

最后,还有我们需要照顾的好朋友 C。所以 ...

于 2009-02-23T16:28:28.797 回答
0

正如其他人所说,您不能修改字符串文字。我还想知道为什么您的代码中没有编译器警告。编译器可以肯定地确定您正在尝试写入只读内存。

于 2009-02-23T16:25:07.887 回答