snprintf()にハマる
C言語の初心者にありがちなミスです.
sprintf()という関数が教科書に書かれていますが,バッファオーバーランを防ぐために,現在ではsnprintf()を使うことが推奨されています.
- sprintf()の例
#include <stdio.h> #include <string.h> int main() { char buf[]="abc"; sprintf(buf,"123456"); /* <---- バッファオーバーフロー */ printf("%s\n",buf); return(0); }
- snprintf)の例
#include <stdio.h> #include <string.h> int main() { char buf[]="abc"; snprintf(buf,3,"123456"); /* <---- バッファオーバーフロー防止 */ printf("%s\n",buf); return(0); }
ところが,「"abc"と3文字分のバッファを用意したから,123と表示されるはず,と思っても,表示されません.
snprintf()の書き込み文字数指定には,文字列末尾の'\0'もカウントしなければならないからです.
「buf[]="abc"」だと,4バイト確保しているので,文字列長は3じゃなくて4を指定しなければなりません.また,わざわざ数える必要もなくて,
- 正しいsnprintf)の例
#include <stdio.h> #include <string.h> int main() { char buf[]="abc"; snprintf(buf,sizeof(buf),"123456"); /* <---- バッファオーバーフロー防止 */ printf("%s\n",buf); return(0); }
でよろしいです(strlen()は'\0'はカウントしませんが,sizeofは'\0'もカウントします).