字符串文字不能被修改(没有未定义的行为)的主要原因是支持字符串文字合并。编译器作者注意到很多程序都有相同的字符串文字重复多次 - 尤其是像模式字符串传递到fopen
(例如,f = fopen("filename", "r");
)和简单格式字符串传递到printf
(例如,printf("%d\n", a);
)。
为了节省内存,他们会避免为这些字符串的每个实例分配单独的内存。相反,他们会分配一个一块内存,并指向它的所有指针。
在少数情况下,它们甚至比这更复杂,以合并甚至完全相同的文字。例如,考虑这样的代码:
printf("%s\t%d\n", a);
/* ... */
printf("%d\n", b);
在这种情况下,字符串文字不完全相同,但第二个是第一端部的相同部分。在这种情况下,他们仍然会分配一块内存。一个指针指向内存的开始位置,另一个指向同一块内存中的%d
位置。
有可能(但没有要求)字符串文字合并,当修改字符串文字时,说出你会得到什么样的行为是不可能的。如果合并字符串文字,修改一个字符串文字可能会修改其他相同或相同的结尾。如果字符串文字不合并,修改一个将不会影响其他任何文字。
MMU增加了另一个维度:它们允许内存被标记为只读,所以尝试修改字符串文字会导致某种信号 - 但只有当系统有MMU时(通常是可选的一次),也取决于编译器/链接器是否决定将字符串文字放在内存中,它们是否标记为常量。
由于他们无法定义修改字符串文字时的行为,他们决定修改字符串文字会产生未定义的行为。
第二种情况完全不同。在这里你定义了一个数组char
。很明显,如果你定义了两个单独的数组,它们仍然是独立的,不管内容如何,所以修改一个不会影响另一个。行为是清楚的,而且一直都是这样,所以这样做给定了行为。有问题的数组可能是从字符串文字初始化的事实不会改变这一点。
http://stackoverflow.com/a/30661089/2912665 – CinCout
无论是作为重复关闭的问题还是由@HappyCoder提及的问题都非常类似于此问题。它们都处理字符串文字的类型。这是问**为什么**字符串文字有这种类型。 –
不只是“会更好”; “将是合法的”。你知道这已被问了一百万次。 –