13

如果我在即时窗口中键入以下内容,则会收到运行时错误“6”:溢出。

MsgBox 24 * 60 * 60

为什么是这样?

这也失败了:

Dim giveTime  As Long 
giveTime  = 24 * 60 * 60

为什么是这样?giveTime被声明为 Long 类型,因此 24 × 60 × 60 = 86400 应该很合适。

4

2 回答 2

33

这是一个非常奇怪的 VBA 怪癖。我很惊讶我从来没有碰到过这个。

Dim x As Long
x = 24 * 60 * 60 ' Overflow
x = 32767 + 1 ' Overflow. 
x = 32768 + 1 ' Works fine!

所以看起来*and+运算符在前两个示例中返回一个整数。果然,在运算符的帮助文件中*(运算符类似+):

结果= number1 * number2

[...]

结果的数据类型通常与最精确表达式的数据类型相同。

默认情况下,您的文字 24、60 和 60 都是 Integer 类型,因此您的*(or +) 运算符返回一个 Integer,它会溢出,因为结果大于 32,767。

但是,上面第三个示例中的文字 32,768 默认为 Long 类型(因为它太大而不能成为 Integer),因此+返回 Long;没有溢出。

帮助文件也这样说:

如果 [...] result的数据类型是超出其合法范围的整数变体[...] 那么result将 [...] 转换为 Long 变体。

强调我的。现在这个小规则听起来像是常识,任何人都会合理地假设它适用于你的情况。但是您的数字是整数类型,而不是 Variant/Integer,因此 VBA 不适用此规则!对我来说绝对没有意义,但这就是事实,这就是文档所说的。

解决方案:使您的*运算符的参数之一是比整数更精确的类型(例如 Long),问题就会消失。

x = CLng(24) * 60 * 60 ' Result is Long, works fine.

事实上,这可能就是我从未遇到过这个怪癖的原因,我养成了将所有 Integer 变量声明为 Long 的习惯,除非特别担心使用 Long 而不是 Integer 会导致内存使用问题或执行时间(几乎从来没有这种情况)。当然,当您对小于 32,768 的文字进行操作时,这将无济于事,因为它们默认为整数类型。


您在评论中询问Variant/Integer 是什么。Variant 基本上是任何其他数据类型的容器类型。在您使其包含整数的特定情况下:

Dim a As Variant ' a is now Empty
a = CInt(32767) ' a is now Variant/Integer
x = a + 1 ' works fine

但如上所述,一个普通的旧 Integer 会触发溢出错误:

Dim b As Integer
b = 32767
x = b + 1 ' overflow
于 2013-06-26T09:22:01.620 回答
5

在每个数字之后,放置#。它将每个数字定义为双精度数。可以将其想象为,每个数字都作为临时变量放入内存中进行计算。如果您定义每个数字,它将为计算留出足够的空间。

例如:

暗淡 x 长

x = 24# * 60# * 60#

或 24&' 表示长

于 2016-09-12T21:59:12.937 回答