使用sprint()时,缓冲区的适当大小是多少

What is proper size of buffer when using sprint()?

本文关键字:多少 缓冲区 sprint 使用      更新时间:2023-10-16

当我想使用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 longn", buffer, n);
return 0;
}

结果:

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

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

没有。

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

否则,请使用更安全的东西:C++中的std::stringstream,或C.中的snprintf和care

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

不是。它正在通过缓冲区的末尾写入其他内存。

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

在您的代码中发生了缓冲区溢出,没有明显的后果,但这并不意味着它工作正常,请尝试使用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");
}

假设代码必须使用sprintf()而不是其他函数:
预先确定最坏情况下的输出大小并添加边距。

除非存在主要的内存问题,否则建议使用2倍的缓冲区。不同的语言环境可以做一些有趣的事情,比如像"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)时,因为输出可能是1000个字符,而应该是x == LDBL_MAX。大约5000个字符,二进制128为长双。

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