我得到了这些测试代码并且好奇,为什么将指针传递给gets()会导致运行时错误?
void main()
{
char *value="gogo";
puts(value);
value="11";
puts(value);
gets(value);
}
答案 0 :(得分:2)
因为char *value="gogo";
更有可能不会分配给 READ ONLY MEMORY !
更好:
#include <stdio.h>
#include <string.h>
#define MAX_LINE 80
int main()
{
char value[MAX_LINE] ="gogo";
puts(value);
strcpy (value, "11");
puts(value);
fgets(value, MAX_LINE, stdin);
puts(value);
return 0;
}
以下是一个包含更多详细信息的良好链接:Storage for Strings in C
PS:
gets()是邪恶的。尽可能避免使用它:Why gets() is bad
答案 1 :(得分:2)
指针value
指向(与字符串文字相关联的静态数组)。
尝试修改字符串文字具有未定义的行为。在这种情况下,您的编译器将字符串"gogo"
存储在操作系统标记为只读的内存中,并且尝试修改它会导致程序崩溃。
如果声明指向字符串文字的指针,则应将其定义为const
:
const char *value = "gogo";
因此编译器将诊断任何修改它的尝试。或者,如果您确实要修改字符串,请将其定义为数组:
char value[] = "gogo";
这意味着您无法为value
分配值,但您可以使用strcpy
进行更新。
还有一些问题:
void main()
错了[*];正确的定义是int main(void)
。如果您使用的是一本告诉您使用void main()
的图书,请找一个更好的图书;它的作者不太了解C.
永远不要使用gets
功能;它本质上是不安全的,并已从语言中删除。 (它不能防止输入比存储值的数组更长。)您可以使用fgets
代替;它使用起来有点复杂,但它可以安全使用。
您需要添加
#include <stdio.h>
到源文件的顶部以使这些函数可见。如果您的编译器没有抱怨对未声明函数的调用,请找出如何提高其警告级别。
[*]说void main()
错误略微夸大了案例。符合标准的编译器可能允许它,并且不需要编译器来抱怨它,但没有充分的理由来利用它。 int main(void)
总是正确的。任何提倡使用void main()
的C书或教程几乎都是由一个不太了解C语言的人写的,可以写书或教程。
答案 2 :(得分:1)
在这里,您的指针指向字符串文字("gogo"
)。字符串文字不保证是可写的。你需要分配自己的记忆:
char value[50] = "gogo";
...
gets(value);
然而,这不安全,因为gets
不占用缓冲区的大小,因此可能会溢出缓冲区。 (这也可能导致运行时错误)。 从不使用gets
,如联机帮助页所述:
<强> BUGS 强>
永远不要使用
gets()
。因为在事先不知道数据的情况下无法判断将会读取多少个字符gets()
,并且因为gets()
将继续存储超过缓冲区末尾的字符,所以使用它是非常危险的。它已被用来打破计算机安全。请改用fgets()
。
分配自己的记忆要好得多:
char user_input[200];
fgets(user_input, 200, stdin);
您可能需要检查user_input
,看看它是否以换行符结尾。如果是,那么fgets
读取整行。如果它没有,则用户在该行中键入超过约200个字符,并且您需要阅读更多内容以获得整行。我在这里使用了200
。选择对您的数据有意义的大小。您还可以使用malloc
即时分配内存,并将fgets放入循环中,以便将整行读入缓冲区。