使用sprint()时缓冲区的大小是多少?

时间:2015-04-18 15:12:01

标签: c++ c

当我想使用sprintf函数时,char数组(缓冲区)的大小是多少?

如果缓冲区只能容纳1个字符,我不知道为什么这部分代码有效?我把更多的字符放在1以内。

/* sprintf example */
#include <stdio.h>

    int main ()
    {
      char buffer[1];
      int n, a=5, b=3;
      n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
      printf ("[%s] is a string %d chars long\n",buffer,n);
      return 0;
    }

结果:

[5 plus 3 is 8] is a string 13 chars long

3 个答案:

答案 0 :(得分:4)

  

当我想使用sprintf函数时,char数组(缓冲区)的大小是多少?

没有。

如果你可以从格式字符串和输入类型中找出上限,那么你可以使用它。例如,32位int赢得超过11个字符以十进制表示并带有可选符号,因此您的特定示例不需要超过44个字符(除非我错误计算) )。

否则,请使用更安全的内容:C ++中的std::stringstreamsnprintf并注意C语言。

  

如果缓冲区只能容纳1个字符,我不知道为什么这部分代码正常工作?

不是。它将缓冲区的末尾写入其他内存。

也许这不会导致任何明显的错误;也许它会破坏其他一些变量;也许它会导致保护错误并结束程序;也许它会破坏堆栈帧并在函数尝试返回时造成各种破坏;或者它可能会导致其他一些未定义的行为。但它肯定行为不正确。

答案 1 :(得分:0)

在你的代码中发生了缓冲区溢出,没有明显的后果,但这并不意味着它正常工作,尝试使用像valgrind这样的内存调试器,你会看到我的意思。

您无法确保sprintf()不会溢出缓冲区,这就是为什么有snprintf()函数可以传递缓冲区大小的原因。

样本用法

char buffer[100];
int  result;
result = snprintf(buffer, sizeof(buffer), "%d plus %d is %d", a, b, a + b);
if (result >= sizeof(buffer))
 {
    fprintf(stderr, "The string does not fit `buffer'.\n");
 }

答案 2 :(得分:0)

假设代码必须使用sprintf()而不是其他功能:
预先确定最坏情况下的输出大小并增加保证金。

除非存在重大内存问题,否则建议使用2x缓冲区。各种语言环境可以执行有趣的操作,例如将','添加到整数输出,如"123,456,789"

#include <stdio.h>
#include <limits.h>
#define INT_DECIMAL_SIZE(i) (sizeof(i)*CHAR_BIT/3 + 3)

#define format1 "%d plus %d is %d"
char buffer[(sizeof format1 * 3 * INT_DECIMAL_SIZE(int)) * 2];
int n = sprintf(buffer, format1, a, b, a + b);

一个具有挑战性的示例是当代码尝试sprintf(buf,"%Lf", some_long_double)时,输出可能是x == LDBL_MAX的1000个字符。大约5000个字符,binary128为双倍。

//                            -   123.............456   . 000000 \0
#define LDBL_DECIMAL_SIZE(i) (1 + 1 + LDBL_MAX_10_EXP + 1   + 6   1)