(Not 1) 由于某种原因评估为 -2

(Not 1) evaluates to -2 for some reason

为什么 (Not 1) 的计算结果为 -2?我希望它的计算结果为 0。

VBA/VBScript 没有真正的逻辑运算符(AND、OR、NOT)。您看到的逻辑运算符实际上是按位运算符,这就是您所得到的。 VBA 玩一些带有 TrueFalse 值的游戏,所以这在大多数情况下都有效,但偶尔你会发现 "gotcha".

在这种情况下,您必须写 If InStr() <= 0 Then,而不是 If Not InStr() Then
而不是 If InStr() Then 你必须写 If InStr() > 0 Then

换句话说:InStr()returns一个。不要试图将其视为布尔值。

1不是True的整数表示,-1是。

Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0

布尔运算符(NotAndOrXOr)在其操作数为布尔值时的行为与 "logical operators" 相同。如果不是,它们的行为就像 "bitwise operators" 但事实是,它们总是 按位。

整数值1转换为布尔值True只是因为True被定义为Not False,这意味着any 非零值是一个布尔值 True。但是,当您将 -1 用于 True.

时,您只会得到 correct/expected 逻辑行为

一个Integer用16位表示,所以1是这样的:

0000 0000 0000 0001

这使得 Not 1 成为:

1111 1111 1111 1110

符号位打开,所以值为负 - trim 无意义的数字,你得到:

10

2 的二进制表示。因此,Not 1-2.

相反,-1 将是:

1111 1111 1111 1111

因此Not -1是:

0000 0000 0000 0000

由于其他答案已经解释了原因,我想重点关注编码实践。

如您所见,Not x 不一定是您想要的。在实践中,你想要更像 Not CBool(x)。但是,CBool() 可能会引发错误 - 例如,CBool(Null) 会产生错误 91(无效使用 null)。

可能声称您可以通过对变量进行强类型化来避免这种情况,但即使不使用 Variant 也不能保证在表达式中 Boolean 将保持 Boolean.示例:

?typename(true and 0)
Integer

实际上,很容易不小心让 VBA 为您进行隐式转换,因此,出于这个原因,改变编码习惯可能更适合您。

为了测试真值,您需要像这样的表达式:

If x Then

对于虚假值,您需要像这样的表达式:

If x = False Then

无论 x 的类型如何,它们都有效,无论它是否是表达式,因此据说与 If x = True ThenIf Not x Then。通过养成这种代码习惯,您可以帮助避免因意外从 Boolean 类型转换并获得按位运算而不是逻辑运算而产生的细微错误。

对于赋值,使用 Boolean 变量将确保它始终被强制转换为 TrueFalse 而不是一些随机数。