明日への断片

ゲーム制作やプログラミング関する記事を中心に更新していこうと思います。

18欠片目:気付きにくいバグ集

 こんにちは。最近金欠のvoidです。近々バイトを始めます。


本日は、エラーは起きないけど思った通りの動作にならなかった時に、自分がよく失敗しているミスや、直すのに時間がかかってしまったバグを集めてみました。

それって本当に条件式?

 
■.変数aと変数bの値が等しいときに処理Aを実行したい!

// 誤
if( a = b)
{
  処理A;
}
// 正
if( a == b)
{
  処理A;
}

誤の場合だと、aとbが等しいかどうかではなく、 a = bの式の評価値、即ちbの値が0以外であれば処理Aは実行されてしまいます。

このミスは、初心者の頃数学記号と混同して使っていたり、タイプミスで = を1個打ち損ねていたときに起こしてしまいます。このようなバグの厄介なところはコンパイルに時エラーにならないことです。

a = bという記述自体に誤りはありませんが、求めているのはa == bの評価値です。

対処法 if文などに使われる条件式では基本的には=で代入することはないので、実行されるはずのない処理が実行されていたら条件式が間違っていないかよく見直す。

制御文の適応範囲

■.次のプログラムで、実行されるのはどの処理?

int a = 1;
int b = 2;

// case1
if( a == b)処理A;

// case2
if( a == b);
{
  処理B;
}

// case3
if( a == b)
  処理C;
  処理D;


正解は、処理Bと処理Dです。


if文などの制御文は基本的に、その次の文までが適応範囲になります。

case1のように、if文と処理を1行で書いても、if文が成立していないため処理Aは実行されません。

case2では、if文の直後にセミコロンが存在しているので、if文の適応範囲はそのセミコロンまでで終わってしまいます。ですから、処理Bは条件に関係なく実行されてしまうのです。

case3では、処理Cがif文の適応範囲内にあるので、今回のif文は成立していないため実行されません。しかし、これもまたここまででif文の範囲は終わってしまっているので、処理Dはif文に関係なく実行されてしまいます。

うーん、どこまでがif文の制御下にあるのかが、非常に分かり辛いですね。

対処法 ネスト(入れ子)構造を利用する

中括弧{}を用いてネスト構造にすることで、どこまでがif文なのかはっきりさせることが出来ます。
先ほどのcase3を例に挙げると、

// case3
if( a == b)
{
  処理C;  // {}の中は字下げ(インデント)する。
}

処理D;

このような構造を作ってあげることで、処理Cだけがif文で制御されていることが分かりやすくなります。

余談。~バグという言葉の重み~

 ゲーム制作を知らなかった頃はゲームのバグは、普通じゃあり得ない挙動をするのがとても可笑しくて笑っていただけの記憶がありますが、今ではすっかり、バグという存在があるだけで、頭を抱える程悩ませてくれる存在となっています。たった数年で言葉の重みはここまで変わるものかと痛感しました...

以上。

 今回は比較的初心者が陥りやすいミスの対処法を書いてみました。
誰か1人でも役に立った方がいらっしゃれば幸いです...

ではまた!