sprintf缓冲区大小

时间:2011-10-30 19:18:03

标签: c buffer printf

我是一名新手程序员,但通常我可以解开自己的问题。这次我解决了这个问题,但它仍然让我感到困惑。一位朋友建议我向这个社区征求意见。

我正在尝试用C打印数字。我有一个使用sprintf执行此操作的功能。数字永远不应超过2位数,所以我使用2个字符的缓冲区。不知何故,这是我的逻辑失败的地方,因为这会通过修改传递给sprintf的变量之一来导致无限循环,但增加缓冲区大小可以解决问题。

这是失败的代码:

#include <stdio.h>

void printarray(int array[][4]) {
  int y;
  int z;
  char buf[2];
  for (y=0; y<4; y++) {
    for (z=0; z<4; z++) {
      sprintf(buf, "%d", array[y][z]);
      printf("buf is %s, y is %d and z is %d\n",buf,y,z);
    }   
  }
}

int main() {
  int arr[4][4] = {  {1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}  };  

  printarray(arr);

  return 0;
}

一旦y到达2,它就会重置为0,从而无限循环。将buf [2]改为buf [8]解决了这个问题。

3 个答案:

答案 0 :(得分:12)

您忘记了NUL终止符。在C中,strings需要为终结符添加额外字符,因此char buf[2]应该char buf[3]才能容纳10到99之间的数字。

顺便提一下,您的代码演示了为什么sprintf是危险的,因为它可以写入输出缓冲区并启用stack smashing attacks。更好的选择是使用snprintf

答案 1 :(得分:3)

C字符串以空值终止。如果您有2个字符(例如“10”),则需要一个大小为2 + 1的空终止符缓冲区。

sprintf()将此添加到缓冲区的末尾;在你目前的情况下,你实际上有一个缓冲区溢出,因为你没有提供足够的空间。

现代,更安全的方法是使用snprintf()来提供缓冲区的长度。

答案 2 :(得分:2)

我假设sprintf在生成的字符串末尾添加\0。因此,例如,如果您打印数字99,您将在缓冲区中获得"99\0",因此对于长度为2的缓冲区,会导致问题。