C言語のよくある間違い

目次

バッファーオーバーフロー

コードに誤りが見られないのに誤作動するとき、バッファーオーバーフローが原因かもしれません。特に変数の値が意図せず変わるなら、真っ先にバッファーオーバーフローを疑ってください。

sprintf関数①

配列のサイズを超える文字列を代入してはいけません。

[不適合例]

char buf[5];
int  line = 5;

sprintf(buf, "line=%d", line);

[適合例]

char buf[10];  // 十分大きいサイズにする
int  line = 5;

sprintf(buf, "line=%d", line);

sprintf関数②

sprintf関数は末尾にNULLが入ります。これを考慮せずに使用すると、NULLがバッファーオーバーフローを引き起こします。これを避けるため配列のサイズはdefineで定義し、変数宣言では「+1」すると良いでしょう。

[適合例]

#define NAME_SIZE (12)

char name[NAME_SIZE + 1];
int  year  = 2000;
int  month = 1;
int  day   = 1;

sprintf(name, "%04d%02d%02d.txt", year, month, day);

配列のサイズを超えないように監視する

通信データの受信を行う場合、受信データが配列のサイズを超えないように監視しなければなりません。

[適合例]

#define COM_SIZE (12)
#define CR (0x0D)

char com_data[COM_SIZE];
int  size = 0;
int  flag = 0;

while (1) {
  com_data[size] = sci_getch();
  if (com_data[size] == (char)CR) {
    break;
  }
  size++;

  // バッファーオーバーフローの監視
  if (size >= COM_SIZE) {
    flag = 1;
    break;
  }
  ...
}

演算誤差

整数除算

演算結果に妙な誤差が発生するとき、整数どうしの除算を行っている可能性があります。浮動小数点数にキャストして演算してください。

[不適合例]

int    a = 3;
int    b = 2;
double c, d;

c = a / b;      // c = 1
d = 3 / 2 * c;  // d = 1

[適合例]

int    a = 3;
int    b = 2;
double c, d;

c = (double)a / b;  // c = 1.5
d = 3.0 / 2.0 * c;  // d = 2.25

オーバーフロー

演算結果がまったく想定していない値になるとき、オーバーフローしている可能性があります。型のサイズを大きくするか、キャストして演算してください。

[不適合例]

// int型が2バイト、符号付き整数が2の補数の処理系とする
int  a = 32767;
int  b = 1;
long c;

c = a + b;  // c = -32768

[適合例]

int  a = 32767;
int  b = 1;
long c;

c = (unsigned long)a + b;  // c = 32768

コメント

コメントする

CAPTCHA


目次