#include <cstdio>
#include <iostream>
using namespace std;
int main ()
{
char buffer [1];
sprintf (buffer, "%d is one number", 1);
cout<<buffer<<endl;
return 0;
}
buffer
的大小只有一个,但cout
可以打印正确的结果。为什么呢?
安全吗?或者,在使用char *
相关方法时,我必须考虑为缓冲区设置一个大的大小?
答案 0 :(得分:0)
不,这不安全。
C样式的字符串需要以null结尾,但buffer
中没有足够的空间。未定义的行为并不意味着保证工作或不工作。当我测试你的程序时,我遇到了分段错误。
答案 1 :(得分:0)
char buffer[1]
不是托管数组。它只是给编译器提示他应该为一个char保留空间。变量缓冲区用作指向该空间的指针,并丢失有关原始大小的所有信息。所以上述陈述与写作相同:
char bufferVar = '\0'; /* a single character */
char *buffer = &bufferVar; /* a pointer to bufferVar */
缓冲区只包含一个字符的地址,但根本没有其他信息! 你的sprintf期望这样一个地址很高兴从缓冲区开始写它的字符串。
分段错误是来自操作系统的消息。您的进程为一个字节分配空间。操作系统以页面(段)管理您的内存。当您跨越这些段的边界时,会引发分段错误。 据我所知,它取决于编译器是否在段的开头或末尾分配变量。
Yu Hao的编译器显然将它们放在最后 - 你的前端。所以你的sprintf不会写一个段的边界。希望它有所帮助。
答案 2 :(得分:0)
至于考虑存储char *
字符串所需的大小,许多C stdlib字符串函数会告诉您传递它们所需的长度NULL
。您可以在为字符串分配存储空间之前调用此方法,以了解所需的存储空间:
std::cout << "You need a buffer that can store "
<< sprintf (NULL, "%d is one number", 1) + 1
<< " characters to safely store your string."
<< std::endl;
另一个解决方案是使用snprintf (...)
之类的东西,它可以保证它会截断输出,使其不会超出你的缓冲区:
snprintf (buffer, 1, "%d is one number", 1);
// ~~~
// Length of buffer
在您的情况下,缓冲区只有1个字符长,因此它只有足够的空间来存储空终止符;不是特别有用。