ActionScript3で便利なuint型。どうせ負の値にならないんだからという理由で、for文のiカウンターやArrayのインデックスなんかに使っていませんか?
あなたのそのuintが狙われています!
軽い気持ちでuintを使う前にまずはご確認を!
そもそもアドビのActionScriptコーディング規約でも
たとえ負の数にはならない場合であっても、整数には int を使います。uint は RGB の色指定、ビットマスク、その他の数値でない値にのみ使用します。
と書いてます。
うん、リンク先消えてた。
なのでtrick7さんが訳してくださったほうを引用しています。
ちょっと試してみます。
var u:uint = 0;
trace(--u); //-1
trace(u); //4294967295
あ、あかんやつや。
var u:uint = 0;
while(--u < 0){
trace(u)
}
//4294967295
もうだめや。
uintが一瞬だけ負の値になるのが確認できます。
これビットで考えないとややこしいのですが、
int型で '00000000000000000000000000000000'(数字が32個)がゼロで
uint型でも '00000000000000000000000000000000'はゼロなわけです。
数字の1は
'00000000000000000000000000000001'
2は
'00000000000000000000000000000010'
3は
'00000000000000000000000000000011'
どんどん増えていって
'01111111111111111111111111111111'(一番上の位が0だけどそれ以外は全部1)
のとき10進数は2147483647になります。
ここまではuintもintも同じなのですが、ここから先はintでは負の数字の世界に入ります。
uintでは
'10000000000000000000000000000000'は
2147483648とマイナスが付かずそのまま数が増えていきます。
どんどん足していって、
'11111111111111111111111111111111'で
4294967295
さたに1足せば
'00000000000000000000000000000000'になって0に循環します。
しかしながらintでは'10000000000000000000000000000000'から負の世界にいくので
-2147483648
となって、そこからどんどん足していって
'11111111111111111111111111111111'
で-1。
さらに1足すと
'00000000000000000000000000000000'になって0となるわけですね。
で、ちょっとやっかいなのがuintの
'10000000000000000000000000000000'
から
'11111111111111111111111111111111'
までの数字。つまりintでいう負の値の世界。
uint型でゼロから-1すると'11111111111111111111111111111111'になるのですが、これが一瞬だけint型で言う-1と解釈されてしまうわけです。
これを回避するためには
if(--u === int(0xFFFFFFFF))
こんな感じでビットを意識して使わないといけないわけです。
僕はビット演算苦手なのでもっといい方法あるかもしれないですが、とにかく何かしら処理を考えないといけないよという。
で、最初に戻りますがたぶんuintをそこまで考えて使ってないのがほとんどだと思います。
プログラム中ゼロになることがないんだからuint使ったれ、くらいの気持ちで。
プログラム実行中に負の値になったらランタイムエラーでも出てくれればまだいいんですけど、実際は負の値になったとき、使ったプログラマの意図とはたぶん真逆の反応をするわけですね。
なので、特にカウンターなど1足したり引いたりする値にはuintは使わないようにするのが吉かと思います。
Array.lengthなど、もとからuint型が返ってくるやつとか格納するのにint型では、もし値が2147483647を超えたらどうなるのか不安かもしれないですが、値が20億超えることよりは-1を下回るほうがよくあることなので、特にです。
そんなことを思いながら酒を飲んでました。