Integer Vs Long Confusion

前端 未结 7 1150
小鲜肉
小鲜肉 2020-11-27 18:49

I have seen many believe in the following

VBA converts all integer values to type Long

In fact, even the MSDN article says

7条回答
  •  刺人心
    刺人心 (楼主)
    2020-11-27 19:28

    As far as my testing goes, A VBA integer still takes two bytes (Tested on Access 2016, build 8201).

    Implicit casting to a long (and back, if it's a write operation) occurs for operations, not for storage, as far as I can find. E.g. if I do myInt + 1, myInt gets cast to a long, then one gets added to that long, and then the result is cast back to an int, resulting in a performance loss compared to just using a Long. So while it costs less memory to use an integer, all operations will suffer in performance.

    As Mathieu Guindon noted under Enderland/Elysian Fields's answer, testing VBA's storage with VBA functions can't prove anything, so let's go more low-level and directly view what's stored in memory, and manipulate that memory.

    First, declarations:

    Declare PtrSafe Sub CopyMemory Lib "Kernel32.dll" Alias "RtlMoveMemory" (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As Long)
    
    Public Function ToBits(b As Byte) As String
        Dim i As Integer
        For i = 7 To 0 Step -1
            ToBits = ToBits & IIf((b And 2 ^ i) = (2 ^ i), 1, 0)
        Next
    End Function
    

    Now, I'm going to prove two things:

    1. The memory VarPtr points to contains 16-bits integers
    2. Manipulating this memory manipulates the integers VBA uses, even if you manipulate it outside of VBA

    The code:

    Dim i(0 To 1) As Integer
    'Using negatives to prove things aren't longs, because of the sign bit
    i(0) = -2 ^ 15 + (2 ^ 0) '10000000 00000001
    i(1) = -2 ^ 15 + (2 ^ 1) '10000000 00000010
    Dim bytes(0 To 3) As Byte
    CopyMemory VarPtr(bytes(0)), VarPtr(i(0)), 4
    Dim l As Long
    For l = 3 To 0 Step -1
        Debug.Print ToBits(bytes(l)) & " ";
        'Prints 10000000 00000010 10000000 00000001
    Next
    'Now, let's write something back
    bytes(0) = &HFF '0xFFFF = signed -1
    bytes(1) = &HFF
    CopyMemory VarPtr(i(0)), VarPtr(bytes(0)), 2
    Debug.Print i(0) '-1
    

    So, we can be certain that VBA indeed both writes 2-byte integers to the memory, and reads them back from the memory, when we're declaring things as an integer.

提交回复
热议问题