【VBA】For ループの罠(?)
次のコードを実行するとどうなると思いますか?
Public Sub foo() Dim i As Long For i = &H7FFFFFFE To &H7FFFFFFF Debug.Print i Next i End Sub
もうひとつ
Public Sub bar() Dim i As Long i = &H7FFFFFFE Do Debug.Print i i = i + 1 Loop Until i > &H7FFFFFFF End Sub
ちなみに、
&H7FFFFFFE => 2147483646
&H7FFFFFFF => 2147483647
です。
どちらも、
2147483646 2147483647
となると思った方
・
・
・
・
・
残念ですが、半分だけ正解です。
bar の方が、予想はしやすいと思いますが・・・
どちらも 2147483646 と 2147483647 は出力されます。
でもその後に、どちらも、オーバーフローが発生します。
上記Forループの場合、変数 i がLongなので、Longの上限値である &H7FFFFFFF までループ可能かと思っていたら、内部で&H7FFFFFFF + 1 してからループを終了するみたいです。
( i = &H7FFFFFFF の処理を終了後、i をインクリメントして i > &H7FFFFFFF となったことでループ終了と判断していると推測される)
ただ、For ループの方のスクリーンショットで見える -2147483648 は、Long の最小値(&H80000000)であるので、この状況についてはよくわからない。
Longの上限(&H7FFFFFFF)を超えた &H80000000(正の値)が、Longの変数領域に負の値の &H80000000 として存在しているためなのか?
内部でのBitは &H80000000 で一致していても、実際には、Longの上限(&H7FFFFFFF)+1(+2147483648 > 0)となるためオーバーフローと判断されたのだろうか?
ちなみに、イミディエイトウィンドウで
? &H7FFFFFFF + 1
とやっても、オーバーフローが発生する。
上記のbarの方は予想はできるけど、For の挙動は予想できなかった。
別の作業で同様の処理をやっていて、順調に進んでいった最後のところで
「えっ、なんでオーバーフローすんの?」って驚いた。
その原因がこんな感じでした。
結 論
- For ループは、ループ変数の型の上限値までループさせるとオーバーフローする。
- ループ変数の型は、余裕のあるサイズにしよう!!!
- 境界には気をつけよう
あぁ、今日も余計な手間で疲れた・・・
回答が・・・
後からブロググループのページを見て・・・
がっかり orz
なんのために結果を隠したんだよ・・・
最初から答えが出てるじゃん。
当該画像の前に別の画像を追加しても、ブログページに表示される画像は変わらないんですね。
しょうがないので、最初から隠さずに全部表示することにしました。
つまらん!