当我想使用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
答案 0 :(得分:4)
当我想使用sprintf函数时,char数组(缓冲区)的大小是多少?
没有。
如果你可以从格式字符串和输入类型中找出上限,那么你可以使用它。例如,32位int
赢得超过11个字符以十进制表示并带有可选符号,因此您的特定示例不需要超过44个字符(除非我错误计算) )。
否则,请使用更安全的内容:C ++中的std::stringstream
或snprintf
并注意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)