Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么字符串文本是常量? 众所周知,C++中的字符串文字是不可变的,修改字符串文字的结果是未定义的。比如说 char * str = "Hello!"; str[1] = 'a';_C++_String_Constants_Literals - Fatal编程技术网

为什么字符串文本是常量? 众所周知,C++中的字符串文字是不可变的,修改字符串文字的结果是未定义的。比如说 char * str = "Hello!"; str[1] = 'a';

为什么字符串文本是常量? 众所周知,C++中的字符串文字是不可变的,修改字符串文字的结果是未定义的。比如说 char * str = "Hello!"; str[1] = 'a';,c++,string,constants,literals,C++,String,Constants,Literals,这将导致未定义的行为 此外,字符串文本被放在静态内存中。所以他们在整个计划中都存在。我想知道为什么字符串文字有这样的属性 修改文字是一种未定义的行为,因为标准如此规定。该标准这样说是为了允许编译器将文本放在只读内存中。它这样做有很多原因。其中之一是允许编译器优化只存储一个在源代码中重复多次的文本实例。因为是K&R C,所以没有“const”这样的东西。类似于ANSI前C++。因此有很多代码都有类似的内容,比如char*str=“Hello!”,字符串文字是“代码> const < /Cord>”

这将导致未定义的行为


此外,字符串文本被放在静态内存中。所以他们在整个计划中都存在。我想知道为什么字符串文字有这样的属性

修改文字是一种未定义的行为,因为标准如此规定。该标准这样说是为了允许编译器将文本放在只读内存中。它这样做有很多原因。其中之一是允许编译器优化只存储一个在源代码中重复多次的文本实例。

因为是K&R C,所以没有“const”这样的东西。类似于ANSI前C++。因此有很多代码都有类似的内容,比如
char*str=“Hello!”const char[]
,但是它们有一个到
char*

的无声隐式转换,原因有两个

一种是允许在只读内存中存储字符串文字(正如其他人已经提到的)

另一个是允许合并字符串文本。如果一个程序在几个不同的地方使用相同的字符串文字,允许(但不一定要求)编译器合并它们是很好的,这样您就可以得到指向同一内存的多个指针,而不是每个指针都占用单独的内存块。这也适用于两个字符串文字不一定相同,但结尾相同的情况:

char *foo = "long string";
char *bar = "string";
在这种情况下,
bar
可能是
foo+5
(如果我正确计算的话)

在这两种情况下,如果您允许修改字符串文字,它可以修改碰巧具有相同内容的其他字符串文字。同时,老实说,这也没有多大意义——有足够的字符串文本可以重叠,这是非常罕见的,大多数人可能希望编译器运行得更慢,只是为了节省(可能)几十个字节左右的内存


在编写第一个标准时,已经有编译器使用了这三种技术(可能还有其他一些)。由于无法描述修改字符串文字所产生的一种行为,而且显然没有人认为这是一种重要的支持功能,因此他们做了一件显而易见的事:即使尝试这样做也会导致未定义的行为。

我相信您会问到文字被放置在 只读内存,与链接器执行此操作的技术细节无关 禁止这样或那样的标准的法律细节

当修改字符串文字起作用时,它会导致微妙的错误 即使没有字符串合并(我们有理由这样做) 如果我们决定允许修改,则不允许)。当你看到这样的代码时

char *str="Hello";
.../* some code, but str and str[...] are not modified */
printf("%s world\n", str);
这是一个自然的结论,你知道将要印刷什么, 因为
str
(及其内容)未在特定时间进行修改 在初始化和使用之间放置

但是,如果字符串文字是可写的,您就不知道它是什么 更多信息:str[0]可以稍后在此代码中或在 深度嵌套的函数调用,当代码再次运行时

不再保证
str
的内容。正如我们 除此之外,此初始化是在移动已知地址时实现的 将时间链接到
str
的位置。它不检查
str
包含“Hello”,但不分配新副本。然而, 我们将此代码理解为将
str
重置为“Hello”。很难理解 克服这种自然的理解,就很难推理出 不保证的代码。当你看到这样的表情
x+14
,如果你不得不考虑14可能被覆盖怎么办 在其他代码中,它变成了42?字符串也有同样的问题

这就是不允许修改字符串文字的原因,无论是在 标准(不要求早期检测故障)和 实际目标平台(提供探测潜力的奖励) 臭虫)

我相信很多解释这件事的尝试都会受到 最糟糕的循环推理。该标准禁止向任何人写信 因为编译器可以合并字符串,也可以放置字符串 在只读存储器中。它们被放置在只读内存中以捕获 违反标准。合并文本是有效的,因为 标准禁止。。。这是你要求的一种解释吗

让我们看看其他的 语言。 修改未定义的文字行为,即使 前面的Lisp的历史与C的历史非常不同 实现。这是因为可写文本在逻辑上是 危险的语言标准和内存布局只反映了这一点 事实

Python语言只有一个地方 “写入文本”可能发生:参数默认值,以及 事实

你的问题被标记为
C++
,我不确定它的当前状态 关于到非常量的隐式转换
char*
:如果是 转换,是否已弃用?我希望其他答案能提供一个答案 在这一点上有充分的启示。当我们谈论其他语言时 这里,让我提到纯C。这里,字符串文字不是常量, 同样要问的问题是,为什么我不能修改字符串 文字(更有经验的人会问,为什么 字符串文本非常量(如果我不能修改它们?)。但是,
上面的推理完全适用于C,尽管有这种差异。C++中的

< P>,字符串文字是“代码> const < /Cord>”,因为您不被允许。 来修改它们。在标准C中,它们应该是
char *str="Hello";
void
mutate(char* p)
{
    static char c = 'a';
    *p = a ++;
}
mutate( "hello" );  //  Can't trust what is written, can you.