如何在VB6中表示64位整数?

时间:2016-11-07 22:02:41

标签: vb6

我不得不扩充遗留应用以处理64位整数。但是,VB6没有这种数据类型。我发现在线的推荐是使用货币数据类型。

但是,我发现我遇到了一些溢出问题。

示例 - CCur通话期间的溢出结果:

dim c as currency

' set maximum value of int64
c = CCur("9223372036854775807")

但是,如果我应用较小的数字(但仍然比int32大得多),它确实有效:

dim c as currency

' Remove the last 4 digits
c = CCur("922337203685477")

那我在这里错过了什么?如何处理64位值?

我需要对64位值执行的唯一操作是从SQL Server存储过程(它是sql类型bigint)中读取它们,然后将其显示在表单中。

4 个答案:

答案 0 :(得分:4)

ADO Field.Value是Variant类型。当您在VB6中检索adBigInt时,Variant将为子类型Decimal。

答案 1 :(得分:1)

答案是,这取决于您对64位值的处理方式。如果您只想保留一个值而不对其进行任何算术,那么创建一个字节数组或长数组可能会更好。例如:

Dim SixtFourBit(7) As Byte

Dim SixtyFourBit(1) As Long

使用货币类型是一种更简单的解决方案,因为您可以对其应用算术。但Currency类型是固定格式表示,总是有四个小数位。这意味着64位表示的低字节构成了Currency值的小数部分(排序)。

要在Currency和数组之间强制使用Devilish CopyMemory windows API函数:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Integer)

Sub SomeFunction()
    Dim AnArray(7) As Byte
    Dim ACurrency as Currency

    ACurrency = 123.4567
    CopyMemory AnArray(0), VarPtr(ACurrency), 8&

    ' Inspecting AnArray in the watch window will show you the byte representation of ACurrency
End Sub

需要注意的是,通常要避免这种诡计。不正确使用CopyMemory会导致您的程序失效。

答案 2 :(得分:1)

您可以将Variant数据类型与CDec()转换一起使用。

dim c as variant

' set maximum value of int64
c = CDec("9223372036854775807")

现在你甚至可以在c上使用标准的vb6数学运算或字符串转换函数。

Dim c As Variant, d As Variant

c = CDec("9223372036854775807")

Dim i As Integer

i = 1000
d = 10

Debug.Print c + i
Debug.Print c / d
Debug.Print CStr(c)

结果

 9223372036854776807 
 922337203685477580,7 
9223372036854775807

请注意,Decimal类型Variant宽于64位,因此您不会在服务器端获得“溢出”:)

答案 3 :(得分:1)

VB6可以与I8的变体类型一起使用,以提供64位带符号整数。 (UI8不适用于VB6)。有一些限制,例如TypeName不起作用,而VarType起作用。

函数cInt64的示例,用于创建64位整数变量,该变量首先创建一个十进制变量,然后将其转换为I8变量:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Enum VARENUM
   VT_I8 = &H14
End Enum ' } VARENUM;

Private Type Dec_Hdr
    DecType     As Integer
    DecScale    As Byte
    DecSign     As Byte
End Type

Function cInt64(v As Variant) As Variant
Dim DecHdr As Dec_Hdr
    cInt64 = CDec(v) ' first create a Decimal Variant
    CopyMemory DecHdr, ByVal VarPtr(cInt64), Len(DecHdr)
'Correct possible CDec conversion errors with Hex strings
    If VarType(v) = vbString Then
        If InStr(1, v, "&h", vbTextCompare) = 1 Then DecHdr.DecSign = 0
    End If
'Remove any decimal places
    If DecHdr.DecScale Then cInt64 = Fix(cInt64)
'Convert Decimal to Int64, setting sign and scale to zero
    CopyMemory ByVal VarPtr(cInt64), CLng(VT_I8), 4 
'Adjust for Decimal Sign
    If (DecHdr.DecSign <> 0) And (cInt64 > 0) Then cInt64 = -cInt64
'Finally check variant is of type I8
    If (VarType(cInt64) <> VT_I8) Then Err.Raise 6
End Function