#include<stdio.h>
int main()
{
char str[10];
scanf("%[^\n]", str);
printf("%s\n", str);
}
当这是编译并且输入为&#34; subhash das india&#34;。 输出与subhash das india相同。 我想知道字符串是如何存储在内存中的,因为str大小为10,并且给定的输入大小大于10.
答案 0 :(得分:0)
printf将继续打印,直到找到null(终止字符):\0
,因此虽然只留出10个字节,但文本仍将放入数组中,因为str只是指向数组的指针。
答案 1 :(得分:0)
数组str
从应用程序的堆栈中获取10个字节。
有些编译器通过简单地计算所有变量,所有函数中堆栈上的数组和结构的字节数加上所有函数参数和函数调用所需的字节数来计算所需的堆栈大小。但是这个堆栈大小计算肯定总是错误的,因为并非所有函数都按顺序调用。
因此,许多编译器通常会定义一个固定的堆栈大小,该大小在调用main之前在应用程序的启动时分配。堆栈大小可以由开发人员控制,例如,当应用程序需要的内容超过应用程序通常需要的时候,因为大量的递归函数调用。
例如,在Visual Studio页面上查看/F (Set Stack Size)。使用Visual C / C ++编译的C / C ++应用程序的默认堆栈大小为1 MB堆栈。
因此,对于简单代码来说,将堆栈上复制超过10个字节的字符串移到str
个指向的位置是没有问题的。来自scanf
的字符串以空字节结束。 printf
只输出字节,直到找到空字节。
但是如果你想通过添加一个函数修改你的代码,该函数还包含一个位于堆栈上的数组,该数组还用某些东西初始化,并且在scanf
和printf
之间调用此函数,你会在输出上看到一个不同的输出字符串。
scanf
和printf
应该不再使用。 C / C ++库和各种框架/库提供了更安全的函数,可以检查字符串数组的大小。
答案 2 :(得分:0)
前十个字符存储在数组中,其余字节存储在内存中的数组之后。你不知道应该在这些字节中存储什么,然而你用字符串"s india"
覆盖它们。这是不好的。尽管它可能在这种情况下有效,但是当你再次运行程序时,它甚至不太可能与不同的编译器/在不同的系统上工作。
printf()
并不关心你覆盖了什么,它只会搜索字符串中的终止空字节,这恰好发生在数组结束之后的某个地方。在您从函数返回(在这种情况下为main()
)之后,意外行为不太可能生效,这可能会发生段错误,或者使用main()
中声明的其他变量,这些变量恰好已被{覆盖{1}}。
请注意,程序的行为完全未定义。它允许格式化你的硬盘。允许将计算机的备份保存到NSA。它允许下载一个漂亮的小程序,它将在您下次尝试进行网上银行时自动重定向您的浏览器。这些都是真正的危险,像您所提供的代码是最容易被利用的安全漏洞的核心。
如果您想要安全,请使用POSIX-2008函数:scanf()
阅读整行,getline()
替换asprintf()
和sprintf()
的使用。标准C库的GNU实现还允许您使用格式strcat()
和"%as"
来为要读取的字符串分配足够的内存,但这不是标准的一部分。 / p>