Part 2.変数の定義域(2)

道場だってば!!


前回、uintとintの違いについて述べたが、uintを使いなさいという意味ではない。違いを意識しなさいということだ。


たとえば個数を表す変数を用意したとしよう。個数はマイナスになることはないから、uintにするのが、正しい。ときどき、わざわざintで引数として受け取って、


if (num<0 || num > max_num) return ;


のように負チェックをしてあるプログラムを見かけるが、最初からuintで受け取ればそんなチェックはいらないのである。


ところが、ループ変数に関しては常にuintにすればいいかと言うとそうでもない。10回まわるループを書いたとしよう。


for( uint i=0; i<10 ; ++i)


ループ変数iの取りうる値は、0から9だと思うかも知れないが、それは違う。取りうる値は、0から10だ。ループを抜け出るときにiは10になっている。このことを意識していないと思わぬところでハマる。


普通はあまり書かないが、たとえば、ループカウンタを1からぶん回したとしよう。


for( uint i=1; i<=10 ; ++i)


このとき、

for( byte i=1; i <= c ; ++i)

(byteとはunsinged charにtypedefしてあると仮定する)


c==255だと、このループは永久ループとなるのだ。なぜなら、このループを脱出するためには、iが256という値を取れる必要があるからだ。


なぜこういうことが起きるのだろうか?


理由は簡単だ。ループ変数をインクリメントして、そのループ変数が範囲を超えたかを調べているからである。つまり、上の例の場合、iは1からc + 1までを扱える整数型でなければならない。c == 255ならば i は1から256まで扱える整数型でなければならない。


同様の理由により、ダウンカウントするタイプのループにおいては、


for( int i=num-1; i>=0 ; --i)


iは、num-1から-1までを扱える整数型(すなわち符号付き整数)でなければならない。「だからループ変数はintのほうがいい」だとかいうのはちょっと違うと思う。要するに、上記のルールを正しく理解しておくことが大切なのだ。