在C ++中使用sprintf时,为什么缓冲区的大小很小

时间:2013-11-29 06:15:52

标签: c++ string printf

#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 *相关方法时,我必须考虑为缓冲区设置一个大的大小?

3 个答案:

答案 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个字符长,因此它只有足够的空间来存储空终止符;不是特别有用。