sprintf buffer sizes

2019-02-25 01:55发布

问题:

I'm a novice programmer, but usually I can unravel my own issues. This time I solved the issue, but it still stumps me. A friend suggested I ask this community for input.

I'm trying to print numbers in C. I have a function to do this using sprintf. The numbers should never be more than 2 digits so I use a 2-character buffer. Somehow this is where my logic fails, because this causes an infinite loop by modifying one of the variables passed to sprintf, but increasing the buffer size solves the issue.

Here's the failing code:

#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;
}

as soon as y gets to 2, it gets reset back to 0, thus infinite loop. changing buf[2] to buf[8] solves the issue.

回答1:

You're forgetting the NUL terminator. In C, strings require an extra character for the terminator, so char buf[2] ought to be char buf[3] to accommodate numbers between 10 and 99.

Incidentally, your code demonstrates why sprintf is dangerous as it can write past the output buffer and enable stack smashing attacks. A better options is to use snprintf.



回答2:

C strings are null terminated. If you have 2 characters ("10" for example) you need a buffer sized 2 + 1 for the null terminator.

sprintf() adds this to the end of your buffer; in your current case you actually have a buffer overflow because you're not providing enough space.

The modern, safer approach is to use snprintf() to which you supply the length of the buffer.



回答3:

I assume that sprintf adds a \0 at the end of the generated string. So for instance if you print the number 99, you'd get "99\0" in your buffer, so for a buffer with length 2, that causes problems.



标签: c buffer printf