空腹おやじのログと備忘録

VBA(主にExcel)でいろいろな実験的な事とか、Linuxのコマンドとか設定とかについて忘れないように、あれこれと・・・

【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
です。

f:id:Z1000S:20190429072820j:plain

どちらも、

 2147483646 
 2147483647 

となると思った方

   ・
   ・
   ・
   ・
   ・

残念ですが、半分だけ正解です。

bar の方が、予想はしやすいと思いますが・・・



どちらも 2147483646 と 2147483647 は出力されます。
でもその後に、どちらも、オーバーフローが発生します。

f:id:Z1000S:20190428223821j:plain
f:id:Z1000S:20190428223837j:plain

f:id:Z1000S:20190428223856j:plain
f:id:Z1000S:20190428223916j:plain

上記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
f:id:Z1000S:20190429073335j:plain
なんのために結果を隠したんだよ・・・
最初から答えが出てるじゃん。

当該画像の前に別の画像を追加しても、ブログページに表示される画像は変わらないんですね。
しょうがないので、最初から隠さずに全部表示することにしました。


つまらん!