#include <stdio.h>
int main(void) {
char arr[10];
gets(arr);//let's suppose input is "abcdefgshsdfhdsfsh"
printf("%s",arr);//output come is same as input but the allocated arr have 10 bytes memory
//and can store only ten characters but how come it's possible i am getting output
//more than 10 character
return 0;
}
输出背后的原因是什么?任何帮助将不胜感激。
答案 0 :(得分:2)
因为在从stdin获取字节并将它们放在某处时,gets不会进行任何检查。一个简单的例子:
char array1[] = "12345";
char array2[] = "67890";
gets(array1);
现在,首先您可以输入您想要的字符数,gets
不会关心它。其次,你放置它们的数组大小的字节数(在本例中为array1
)将覆盖它们在内存中找到的任何内容,因为gets
将写入它们。在前面的例子中,这意味着如果您输入“abcdefghijklmnopqrts”可能,不可预测,它也会覆盖array2
或其他任何内容。
该功能不安全,因为它假定输入一致。千万不要用它!
更安全的方法是fgets()
所以,你想避免gets
。 fgets
将始终读取新行,如果缓冲区大到足以容纳它(这会让你知道缓冲区何时太小而且有更多的行等待读取)。如果你想要fgets
之类的东西不会读取新行(丢失指示太小的缓冲区),你可以使用fscanf
进行扫描集转换,如:“%N [ ^ \ n]“,其中'N'被缓冲区大小替换为-1。
使用fgets
阅读后,从缓冲区中删除尾随换行符的一种简单(如果很奇怪)方法是:strtok(buffer, "\n");
这不是strtok
的用法。 ,但我用这种方式比预期的方式更常用(我通常会避免)。
来源:从我保存的问题中复制。
答案 1 :(得分:0)
未定义的行为意味着程序不遵循该语言的规则,并且编译器不会对结果行为做出任何承诺。
因此,当您在数组的末尾写入时,这是未定义的行为,该语言不会保证它会让您知道错误。它似乎可行,可能会崩溃。今天可能会做一件事,明天可能做另一件事。
有点像把50磅的东西放在一个额定容量为20磅的架子上。也许它会坚持下去,也许它会立即崩溃。也许它会坚持到你拿走一些东西然后崩溃了。
答案 2 :(得分:-2)
C字符串(类型char
的数组)需要一个终止空字节来指示字符串的结尾。当正在处理字符串的字节时,例如printf()
,当达到null时,该函数将停止处理这些字节。由于超出了数组的长度(并且在与数组相邻的任何内存中,最后的空字节已经放置在距离数组起点10个字节以外),因此该函数在未定义的字节数时继续执行印刷。