【VBA実験】何回NotしてもTrueになるTrueを作る
あけましておめでとうございます。 今年もよろしくお願いいたします。
前書き
私が職場で使っているVBAのライブラリの中には、「何回NotしてもTrueになるTrue」を返すAPIを持つものがあります(一般には使われていないライブラリ)。
この「何回NotしてもTrueになるTrue」をVBAだけで作成する方法の記事となります。
そのため、実際のコードに役立つことはほぼ無いでしょう。
VBAのBoolean周りの動作
本来、VBAのTrueは、16bitの符号付き整数で表すと-1
になります(VBAの16進数表現で&HFFFF
)。
これを、Not
演算子でビット単位で否定すると0
(&H0000
)、すなわちFalseになります。
対して、問題のTrueは16bitの符号付き整数で表すと1
(&H0001
)になっており、これに対してNot
演算子を使用すると-2
(&HFFFE
)、0ではないためTrueになります。
コード
以下のコードにあるGetTrueNotTrue()
関数の返り値が「何回NotしてもTrueになるTrue」になります。
Private Type intType Value As Integer End Type Private Type boolType Value As Boolean End Type Function GetTrueNotTrue() As Boolean Dim i As intType i.Value = 1 Dim b As boolType LSet b = i Let GetTrueNotTrue = b.Value End Function
コードの解説
普通に数値をBoolean型の変数に代入しても、自動型変換が行われ、VBA本来のTrue・Falseとして代入されてしまいます。
今回は数値のバイナリ表現を保ったまま、Boolean型の変数に代入したいため、別の方法をとる必要がありました。
上記のコードでは、ユーザー定義型のバイナリコピーができるLSet
ステートメントを使用し、Integer型の1
のバイナリ表現をBoolean型にコピーしています。
Private Type intType Value As Integer End Type Private Type boolType Value As Boolean End Type
で入れ物となるユーザー定義型を定義します (VBAではIntegerもBooleanも2バイトの領域を必要とします)。
Dim i As intType i.Value = 1
でInteger型の1
を設定、
Dim b As boolType LSet b = i
で別のユーザー定義型にバイナリコピーしています。
動作の確認
Private Sub Sample() Debug.Print GetTrueNotTrue() '-> True Debug.Print Not GetTrueNotTrue() '-> True Debug.Print CInt(GetTrueNotTrue()) '-> 1 End Sub
無事、「何回NotしてもTrueになるTrue」を作成できました。