unsignedの落とし穴

よく見かけるバグのパターンなんかも、ちょっとずつ紹介していこうかなと思います。
最初のテーマは、符号無し型(unsigned)の落とし穴です。

符号無し型を、符号有り型(signed)と混在させて使い、結構いろんなバグの原因になっているのをよく見かけます。
次の例は、実際に経験された方も多いのではないでしょうか。

typedef unsigned int UINT;

{
UINT data[MAX];
UINT i;

for (i = MAX - 1; i >= 0; i--) {
/* dataの処理 */
func(data[i]);
}
}

実際に、上記のようなコードを書いて実行すると何が起こるでしょう?
答えは、永久ループです。

iはunsignedのため、決して0未満にはならないのです。
i==0の時の、i-1は、-1ではなく、0xffffffff(intが32bitの場合)です。

iがintあるいは他のsignedなら何の問題もないのですが、iの比較対象がunsigned型の定数だったりすると、コンパイル時にwarningが出て、ついついiの型をUINTで宣言してしまうことがあります。
そもそも、逆順に処理している(i--)が問題なのですが、これは事情によってそうせざるを得ないこともあります。

例えば、対応は下記のようになります。

{
UINT data[MAX];
UINT i;

for (i = MAX; i > 0; i--) {
/* dataの処理 */
func(data[i - 1]);
}
}

unsignedには他にもいろいろ注意が必要なので、またおいおい紹介していきます。

コメント

非公開コメント

本のおすすめ

4274065979

4844337858

482228493X

4904807057

4873114799


プロフィール

  • Author:proger
  • 組み込み関係で仕事してます

ブログ内検索