我今天正在读一本关于 C 的书,它提到以下内容是正确的;我很好奇为什么要制作这个程序来验证;然后最终将其发布在这里,以便比我聪明的人可以教我为什么这两种情况在运行时不同。
问题的细节与运行时如何处理 (char *) 之间的差异有关,具体取决于它是否指向作为文字创建的字符串与使用 malloc 和手动填充创建的字符串。
为什么内存分配的内存这样更受保护?另外,答案是否解释了“总线错误”的含义?
这是我编写的一个程序,它询问用户是否要崩溃,以说明程序编译良好;并强调在我的脑海中,两个选项中的代码在概念上是相同的;但这就是我在这里的原因,以了解他们为什么不在这里。
// demonstrate the difference between initializing a (char *)
// with a literal, vs malloc
// and the mutability of the contents thereafter
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main() {
char cause_crash;
char *myString;
printf("Cause crash? ");
scanf("%c", &cause_crash);
if(cause_crash == 'y') {
myString = "ab";
printf("%s\n", myString); // ab
*myString = 'x'; // CRASH!
printf("%s\n", myString);
} else {
myString = malloc(3 * sizeof(char));
myString[0] = 'a';
myString[1] = 'b';
myString[2] = '\0';
printf("%s\n", myString); // ab
*myString = 'x';
printf("%s\n", myString); // xb
}
return 0;
}
编辑:结论
下面有几个很好的答案,但我想在这里简洁地总结一下我所理解的。
基本答案似乎是这样的:
当编译器看到将“字符串文字”分配给 (char *) 变量时,指针将指向静态内存(可能实际上是二进制文件的一部分,但通常由比您的低级系统强制执行为只读)换句话说,内存可能不是在程序的那个部分动态分配的,而是指针被简单地设置为指向一个静态内存区域,该区域包含您的文字内容。
关于这个决议,我想指出几点:
1.优化可能是一个可能的动机:使用我的编译器,使用相同字符串字面量初始化的两个不同 (char *) 变量实际上指向相同的地址:
char *myString = "hello";
char *mySecond = "hello"; // the pointers are identical! This is a cool optimization.
2有趣的是,如果变量实际上是一个字符数组(而不是 (char *)),则 (#1) 不正确。这对我来说很有趣,因为我的印象是(编译后)数组与指向字符的指针相同。
char myArString[] = "hello";
char myArSecond[] = "hello"; // the pointers are NOT the same
3总结几个答案暗示的内容:char *myString = "Hello, World!"
不分配新内存,它只是将myString设置为指向已经存在的内存;也许在二进制文件中,也许在特殊的只读内存块中......等等。
4我通过测试发现char myString[] = "Hello, World!"
确实分配了新的内存;我想......我所知道的是,以这种方式创建的字符串是可变的。