ひとつ前の記事で、unsignedを追放しろ、という話をした。続きの話として、unsignedの有効性について述べてみようと思う。
負がないけどsignedの倍までいけるぜ! なんてのは、大した話ではない。今日びそんなことを誰が気にするというのか。世の中はみんな富豪なのだ。2Gで足りなければ4Gなんてセコいことを言う奴を尻目に迷わずlong longと打つし、それで駄目なら迷うことなくGNU mp(gmp)だろう。
unsignedで唯一良いところは、境界チェックが楽だというのがある。これも充分セコいけどね。
つまり配列の添字みたいな値を0〜1024に制限したいとする。signed intなnが与えられると、
if(0<=n && n<1024){ // OK }
といったコードになるだろう。しかし、unsigned intなnならば、
if(n<1024){ // OK }
で済む。なぜならアンダーランも<1024でどうにかできるからである。-1は4294967295なので<1024の真偽だけでチェックできる。
しかしこれってチェックするなら比較のときだけキャストすりゃいいんだよね。
if((unsigned)n<1024){ // OK }
見た目は増えてるけど、例えばx86だと単に比較の後のbranchのインストラクションが変わるだけだから、2回比較するよりも2倍高速(!)というわけで、巷でよく使われているテクニックだと思う。計算機がいろいろとzero-originになってるのはこのためというのもあるんだよ!(へぇへぇへぇ)
…って、普段はsigned intで持って必要なときだけキャストしろって話か。結局unsigned擁護になってないよ(笑)。
プログラマって、暇な時間さえあればこういうセコいことをしようとするんですよね。だから余計にバグるのか!