通过指针与数组写入字符串文字

Writing to string literal through pointer vs. array

在K&R C(第2版)的第5章中,给出了以下两种说法,据说有细微差别(我是照原样粘贴的)

There is an important difference between these definitions:

char amessage[] = "now is the time"; /* an array */

char *pmessage = "now is the time"; /* a pointer */

amessage is an array, just big enough to hold the sequence of characters and '[=12=]' that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.

我不明白他们想在这里暗示什么。它表示对于 pmessage,如果您尝试修改字符串常量,结果是未定义的。他们说的结果是什么,我们怎么修改字符串常量,为什么结果会是未定义的?

它还说 amessage 总是指向相同的存储。这个存储是数组在定义时分配的存储吗?

谁能用更好的方式解释一下?我将不胜感激!!

What is the result they are talking about,

运行 代码的结果。它可能会工作,也可能会崩溃,还有很多其他事情。

how can we modify the string constants

你不能,除非编译器通过某种扩展提供它。如果需要修改,请不要使用字符串文字。

and why will the result be undefined ?

因为标准是这么说的

可以提到,在C++中,字符串文字的类型是const char[],但在C中是char[]。这是历史原因。

这是未定义的原因是因为不能保证在每个体系结构上。

在旧机器上(比如 Amiga 1000)你没有 MMU,所以如果你写到“禁止区域”它会工作。在现代平台(如 Linux 或 Windows 等)上有一个 MMU,它可以防止写入某些区域。 一般这样的字符串常量都放在只读区,如果平台支持的话会抛出异常。 这就是它未定义的原因。该语言不能保证在所有情况下都会发生某种行为,因此它可能有效,也可能无效。

将它放在一个数组中,将始终保证这一点,但使用带有指针的字符串文字,则不能。

What is the result they are talking about, how can we modify the string constants and why will the result be undefined ?

未定义的行为没有特定的结果,对于调用未定义行为的格式错误的程序没有任何要求,这意味着它可以做任何事情。尝试修改字符串常量的程序就是此类程序的一个示例。

你可以查看未定义行为的C11定义here

Also it says that amessage always points to the same storage. Is this storage the storage the array is allocated when it gets defined?

amessage 就是所谓的固定大小数组,它是给定内存地址的别名,一旦它被初始化为该内存地址,它就不能更改,直到变量生命周期结束, points 部分不是我会使用的部分,它可以说是糟糕的措辞,因为 amessage 不是指针,更多关于 here.

另一方面,

*pmessage 是一个指针,因此你可以让它指向其他内存地址,你甚至可以让它指向 amessage pmessage = amessage,现在pmessage指向与amessage完全相同的位置,现在可以访问amessage或通过该指针进行修改,但 amessage = pmessage 是不可能的。