整数与长期混乱

Sid*_*out 22 vba

我见过很多人相信以下内容

VBA将所有整数值转换为Long类型

事实上,即使是MSDN文章也

"但是,在最近的版本中,VBA将所有整数值转换为Long类型,即使它们被声明为Integer类型."

在此输入图像描述

这怎么可能?考虑这个简单的例子.

Sub Sample()
    Dim I As Integer
    I = 123456789
End Sub
Run Code Online (Sandbox Code Playgroud)

如果VBA将所有Integer值转换为类型,Long 即使它们被声明为Integer类型,那么上面的代码永远不会给你Overflow错误!

我在这里错过了什么?或者,我是否应该认为该陈述是错误的并且在开头时注意到该链接所说的内容

Rub*_*uck 10

声明为an的整数Integer仍被类型检查为Integer.msdn文档引用了内部存储变量的方式.在32位系统上,整数将存储在32个BITS而非字节中,而在16位系统上,该值存储在16 位空间或寄存器中,它将存储在16中.因此最大大小.

就VBA而言,没有类型转换.int是一个int而long是long,即使它们现在占用的空间也很大.

  • 我知道Integer和Long如何存储在内存中.`就VBA而言,没有类型转换.即使我相信:)只是声明`如果VBA将所有Integer值转换为Long类型,即使它们被声明为Integer类型'也是非常误导的而且我认为可能还有一些我不知道的事情. (7认同)
  • 就像其他答案所述,这不太可能是真的。VBA `Integer` 似乎不需要 32 位,无论是在 32 位还是 64 位系统上。通过声明一个 `Integer` 数组并观察结果内存布局,或者通过声明单独的 `Integer` 变量并检查它们的 `VarPtr` 很容易验证。 (2认同)
  • 我相信 MSDN 作者没有准确解释他们的意思。考虑到可观察的 `VarPtr`s,为了使这篇文章成为真实,需要有一个完整的虚拟内存层,专门用于隐藏 `Integer` 变量的真实地址(现在需要 32 位),它可以在所有场景中工作,包括互操作. 我不相信他们实际上实现了类似的东西,只是为了可以在内部将 `Integer`s 存储为 `Long`s。 (2认同)

Bat*_*eba 6

我花了很多时间在VBA环境中工作,并且完全有理由相信本文中的主张充其量只是误导.

我从来没有遇到过自动意外转换的情况.当然,按值分配给更大的类型(例如a DoubleLong)将是隐含的.

自动转换将是一个突破性变化的一个特定情况是对Variant类型的赋值.如果没有转换,则类型为VT_I2,转换为VT_I4.

将Integer类型传递ByRef给期望Long在Office 2013中发出类型不匹配的函数.

我怀疑它们指的是内部存储Integer:很可能它们没有在内存中的16位字上对齐(参见shortC/C++中的结构成员).他们可能在谈论这个问题.


end*_*and 5

“但是,在最新版本中,VBA将所有整数值都转换为Long类型,即使它们被声明为Integer类型也是如此。”

我不相信该文档。考虑以下简单示例(在Excel 2010中运行):

Sub checkIntegerVsLong()

    'Check the total memory allocation for an array
    Dim bits As Integer 'or long? :)
    Dim arrInteger() As Integer
    ReDim arrInteger(1 To 5)
    arrInteger(1) = 12
    arrInteger(2) = 456
    'get total memory allocation for integer in array
    bits = VarPtr(arrInteger(2)) - VarPtr(arrInteger(1))
    Debug.Print "For integer: " & bits & " bits and " & bits * 8 & " bytes."


    Dim arrLong() As Long
    ReDim arrLong(1 To 5)
    arrLong(1) = 12
    arrLong(2) = 456

    'get memory allocation for long
    bits = VarPtr(arrLong(2)) - VarPtr(arrLong(1))
    Debug.Print "For long: " & bits & " bits and " & bits * 8 & " bytes."

End Sub
Run Code Online (Sandbox Code Playgroud)

打印:

对于整数:2位和16字节。

长:4位和32字节。

您还可以使用以下方法在各个变量上进行测试:

Sub testIndividualValues()

    Dim j As Long
    Dim i As Integer
    Dim bits As Integer

    bits = LenB(i)
    Debug.Print "Length of integer: " & bits & " bits and " & bits * 8 & " bytes."
    bits = LenB(j)
    Debug.Print "Length of long: " & bits & " bits and " & bits * 8 & " bytes."



End Sub
Run Code Online (Sandbox Code Playgroud)

哪个打印

整数长度:2位16字节。

long的长度:4位和32字节。

最后,您可以在此处使用类型比较:

Public Type myIntegerType
    a As Integer
    b As Integer
End Type
Public Type myLongType
    a As Long
    b As Long
End Type

Public Sub testWithTypes()
    Dim testInt As myIntegerType
    Dim testLong As myLongType
    Dim bits As Integer

    bits = VarPtr(testInt.b) - VarPtr(testInt.a)
    Debug.Print "For integer in types: " & bits & " bits and " & bits * 8 & " bytes."

    bits = VarPtr(testLong.b) - VarPtr(testLong.a)
    Debug.Print "For long in types: " & bits & " bits and " & bits * 8 & " bytes."

End Sub
Run Code Online (Sandbox Code Playgroud)

打印:

对于整数类型:2位和16字节。

对于长类型:4位和32字节。

对我来说,这是非常有说服力的证据,表明VBA实际上确实对待Integer并且Long有所不同。

如果VBA在后台静默转换,则您希望这些指针为每个指针分配位置返回相同数量的位/字节。但是在第一种情况下,对于Integer,它仅分配16位,而对于Long变量,它分配32位。

所以呢?

所以对你的问题

如果VBA即使将所有Integer值都声明为Integer类型,也将所有Integer值转换为Long类型,则以上内容永远不会给您带来Overflow错误!

它使完整意义上,你会得到一个溢出错误,因为VBA没有实际分配的内存LongInteger声明。

如果在所有版本的Office上都返回相同的值,我也很好奇。我只能在64位Windows 7上的Office 2010上进行测试。

  • 我不认为您可以使用VBA代码*来测量VBA的内部存储空间...如果Microsoft修改了VBA运行时以在内部使用32位整数,那么传播对语言的修改将是意料之外的重大变化:认为VBA代码不能证明有关VBA内部的任何信息。 (4认同)