一、微软官方定义
布尔变量作为 16 位(2 字节)数字存储,但它们只能是 True 或 False 。
布尔 变量显示为:
True 或 False (使用 打印 时) 或
#TRUE#或使用#FALSE#写入 #时 () 。
使用 关键字True 和 False 将两种状态之一分配给 布尔 变量。
将其他数值类型转换为布尔值时,0 将变为 False,所有其他值均变为 True。
将布尔值转换为其他数据类型时,False 将变为 0,True 将变为 -1。
从官方定义来看,Boolean既包含了现代布尔值的通用定义,又包含了BASIC的先古定义。虽然能将兼容做到极致,但也确实构成Boolean类型,在应用中产生Bug源头。
现在的疑惑便是,True关键字为何为-1(0xFFFF),这究竟有哪些考量呢?
二、历史中的True和False
在8位BASIC时代,CPU以千赫兹为单位,内存以千字节为单位,而存储设备则更是罕见和昂贵的。那时现代大部分高级开发语言都还未诞生,编程语言自然不会很复杂。
比如Dartmouth BASIC(1964年,达特茅斯学院开发的早期BASIC版本,可参考《VB前传,从教学到游戏,再到系统,似乎每步都是精心设计》),没有AND/OR/NOT运算符,甚至也没有IF关键字。
直到1975年,微软的Altair BASIC,才将AND/OR/NOT运算符添加进来,并且被描述为LOGICAL AND BITWISE(逻辑和按位),并且对于IF的任何非零表达式执行THEN子句。与此同时,False被定义为0(0x0000),True被定义为-1(0xFFFF)。
三、为何要将True映射为-1,而不是非0?
无论怎么说,短周期的AND/OR/NOT,作为整数运算符,将其添加到表达式中,都是一项简单而高效的工作。但是在逻辑表达式中,对于非零值,添加额外的运算符,都可能导致跳转,这无疑会增加表达式设计上的复杂性。这在当时的硬件水平来说,也会降低代码的性能。
但将True映射为-1(0xFFFF),就可将布尔运算与按位运算进行整合,上面的困惑就迎刃而解了。
Not True=False,Not False=True,True And True=True,True And False=False,False And False=False,True Or True=True,True Or False=True,False Or False=False。
这样既借了整数运算的高效,也让表达式更符合直观常识,可谓一举双得。
四、Boolean的发展与进化
随着硬件迭代升级,开发语言也是不断推陈出新。BASIC走进历史,被VB/VBA接棒,Boolean中的非0值导致的表达式问题,也不再构成性能影响。为了与更现代的Boolean标准接轨,VB/VBA的Boolean,自然也纳入非0为真,0为假的概念。
但同时,又以常数True(0xFFFF)和False(0x0000)的方式,继续兼容保留BASIC时期的Boolean特征。
因此VB/VBA中,对于Boolean类型,是要区分变量和常量的。
五、代码测试
True和False是VB/VBA中定义的两个常量,其中True为-1(0xFFFF),False为0(0x0000)。如有怀疑,可以使用Hex函数进行验证。
Private Sub Command1_Click()
Dim blA As Boolean
blA = False: Debug.Print Hex(blA)
blA = True: Debug.Print Hex(blA)
blA = 2: Debug.Print Hex(blA)
Debug.Print blA
Debug.Print String$(10, "-")
Debug.Print Hex(True)
Debug.Print Hex(False)
Debug.Print String$(10, "-")
Debug.Print Not True
Debug.Print Not False
Debug.Print String$(10, "-")
Debug.Print True Xor &HFFFF '等于 &HFFFF Xor &HFFFF
Debug.Print True Xor 0 '等于 &HFFFF Xor &H0000
End Sub
运行结果:
0
FFFF
FFFF
True
----------
FFFF
0
----------
False
True
----------
0
-1