VBAで定数の宣言にデータ型を指定するAsほにゃららを書きますか?
- KotorinChunChun
- 6561
- 14
- 0
- 0
@KotorinChunChun VBAは、全ての整数表現をまずはIntegerで考えようとするので、リテラル値の評価時に指定しないとダメ、という話ですね。 自分も一時期悩まされました。
2020-02-12 20:38:49@nukie_53 @KotorinChunChun これって、constの型というよりclngの問題な気がするのですが、どうなんでしょうか。
2020-02-12 21:07:49@yamaoka_ss @nukie_53 質問の意味が私にはイマイチ分かりませんorz (この場合、CLng()は関係ないんじゃないかな?って) (VBAのリテラルを解釈する仕組みの問題的な?)
2020-02-12 21:29:47@KotorinChunChun @nukie_53 すみません、ぱっと見で反応してしまった部分もあるのですが、 画像のようなことかなと思ったので。 例えば、 Const i As Long = 5.5 これは、6になるので。 pic.twitter.com/Zl5hu1AWu7
2020-02-12 21:34:09@yamaoka_ss @nukie_53 確かにConst に限った話じゃないので、あらゆる場面で起こりますよね。常に気をつけなければ。 5.5が6になるのは、別件のような気もしますね。 VBAが実数を整数に暗黙的にキャストする時は、なぜか丸めが起こるという・・
2020-02-12 22:53:51@KotorinChunChun @nukie_53 はい、つまり言わんとしたのは、longにリテラルをいれる場合全般の話であって、constの型の話とはちがうのではないか、ということです。
2020-02-12 23:05:16@yamaoka_ss @nukie_53 全くもって仰るとおりですね。 私がここでヤバいと思ったのは、Constで型指定をする理由として 「型指定をしないと思わぬ挙動をしそうで怖い」 が多く挙げられると思うからです。 これが転じて 「型指定をしているConstの宣言は安全である」 と信じていたら、罠にハマるからヤバいぞと思った訳です。
2020-02-12 23:11:15@yamaoka_ss @nukie_53 特に16進数リテラルってConstで設定する傾向が強い気がするので、この組み合わせのバグは起こりやすいんじゃないかなと。(私だけ?) だから、Constの型指定を気にする人は、値の方にも型指定しましょうね!(軽い煽り)と言いたかったのですが、上手く意図は伝わって無さそうです。
2020-02-12 23:13:29@KotorinChunChun @nukie_53 はい、16進はやってしまいますので要注意だと思います。 追加で言うなら、 Const i = 10000 Debug.Print i * 10 これはエラーになりますので、型指定もしくは型文字どちらかは必要だと思います。
2020-02-12 23:16:45要するに 両辺の型指定がされていないことによる問題 です。
Const i = 10000&
Debug.Print i * 100&
で十分ですが、As Longは &を付けない人対策 で書いたほうが安全と言えるでしょう。
まとめ
結果はこのようになりました。 8割の方は書く派みたいですね! pic.twitter.com/JUWw7nSdEr
2020-02-13 00:35:24本日のアンケートはこのような結果になりました。
書かない:21%
書く:79%
As ほにゃらら
を書かないことによるリスクを懸念しての投稿でしたが、直接的なリスクはなさそうだと言う事が分かりました。
しかし、全然別の視点において、書いておくのは一定の効果がある事も分かりました。
- 32767以下の整数で宣言した場合にIntegerになってしまう。
- Integer同士で計算させて結果が32768を超えるとオーバーフローする
- よって、
As ほにゃらら
を書く書かないに関わらず、すべてのリテラルには型指定文字を書いた方が安全である。
Sub Test()
Const NUM1 As Long = 32767 'Longになる
Const NUM2 = 32767& 'Longになる
Const NUM3 = 32767 'Integerになる
Debug.Print NUM1 + 1& ' long + long = long : 安全
Debug.Print NUM1 + 1 ' long + int = long : 安全
Debug.Print NUM2 + 1& ' long + long = long : 安全
Debug.Print NUM2 + 1 ' long + int = long : 安全
Debug.Print NUM3 + 1& ' long + long = long : 安全
Debug.Print NUM3 + 1 ' int + int = int : 32768以上はオーバーフローする
End Sub
くれぐれも、ご安全に!!!
また
・アンケートに答えてくださった方
・リプライで反応をくれた方
・更には色々な意見をくださった方
いつも有難うございます。