关于负数溢出问题各位大哥,有事请教一下:我从D11564,D11565取值分别赋给A,B,然后把这两个值合为1个32Bit数
关于负数溢出问题
各位大哥,有事请教一下:
我从D11564,D11565取值分别赋给A,B,然后把这两个值合为1个32Bit数据,如果D11564,D11565为正值的话没有问题,但如果为负值的话(比如D11564为-30168)就会出错:实时错误6,溢出
Private Type DBit16
h As Integer
i As Integer
End Type
Private Type Bit32
data As Long
End Type
Private Sub Command2_Click()
Dim dd As Bit32, tt As DBit16
Dim Ret As Long
Dim SRet As Long
Dim A As Long
Dim B As Long
'Dim c,d as integer
Ret = ActEasyIF1.GetDevice("D11564", A)
SRet = ActEasyIF1.GetDevice("D11565", B)
'c = CInt(A)
'd = CInt(B)
tt.h = A
tt.i = B
'tt.h=c
'tt.i=d
LSet dd = tt
MsgBox dd.data
End Sub
调试时如果把tt.h=A改为tt.h=-30168(不从D11564取值)的话就没有问题,
同时,
Private Sub Command2_Click()
Dim dd As Bit32, tt As DBit16
Dim Ret As Long
Dim SRet As Long
Dim A As Long
Dim B As Long
'Dim c,d as integer
Ret = ActEasyIF1.GetDevice("D11564", A)
SRet = ActEasyIF1.GetDevice("D11565", B)
MsgBox A
End Sub
此时D11564的值为-30168,但输出值却是35368
请教各位大哥那个地方有问题啊??
[最优解释]
很明显, GetDevice() 函数只返回 16 位值,所以变量 A、B 应该定义为 Integer 类型。
原因:计算机中存储的二进制数本身是无明确意义的,用不同的方式解读就会得到不同的结果。
详细分析:
原始数值 -30168 为 Integer 类型,用十六进制表示为 &H8A28。
A 变量为 Long 类型,初始值为 0,用十六进制表示为 &H00000000&;
经过 GetDevice() 函数调用复制了 16 位,其十六进制表示为 &H00008A28&,其数值为 35368。
调用 tt.h = A,因为 h 为 Integer 类型,取值区间为 [-32768, 32767],要赋的值超过这个区间,溢出错误。
[其他解释]
问题的核心是,-30168 最初是当作什么数据类型读入的。
如果一开始从文本读进来,就当作 Integer 解析的,那么无论是有符号数 -30168,还是转成无符号数 35368,它在内存中的存储内容是一样的,即 &H8A28,可以作为一个 Integer 传递。当它和低半字 1 组合成 &H18A28 时,作为 Long 型解释,就是 100904。
问题可能出在你最初是将 -30168 当作 Long 处理的,变成了 &HFFFF8A28。再将它赋给一个 Integer 时就一定会溢出了。
[其他解释]
Function LoWord(ByVal v As Long) As Integer
Dim dd As Bit32, tt As DBit16
dd.data = v
LSet tt = dd
LoWord = tt.h
End Function
Private Sub Command2_Click()
...
tt.h = LoWord(A)
...
End Function
又 Bit32 的结构成员命名不清楚,建议如下
Private Type DBit16
Lo As Integer 'Low Word
Hi As Integer 'High Word
End Type
[其他解释]
很简单, 因为这个D11565被定义成了integer类型了. 找到它的出处, 改成long即可
------其他解决方案--------------------
WallesCai,不行啊,我有改为Long型,改了后不会报错,但取到的数值是错误
[其他解释]
按照你的规则,高半字为负数的输入应该生成怎样的 Long 型数字?
能否给个例子?
[其他解释]
两个有符号的int怎么能合并成一个long那?
没这样的规则呀,你制定个规则才好合并.
如果你要合并两个无符号的int,那还可以考虑下...
[其他解释]
GetDevice()函数已固定为Long类型,
---------------------------------
格式
Visual BasicR 6.0、VBA:lRet = object.GetDevice(szDevice、lData)
Long lRet 返回值 输出
String szDevice 软元件名称 输入
Long lData 获取数据 输出
---------------------------------
如果把A,B修改为Integer类型则会报类型错误,A,B只能定义为Long型,但我有试过A,B得到值后强制转为Integer型,
Dim c,d as integer
Ret = ActEasyIF1.GetDevice("D11564", A)
SRet = ActEasyIF1.GetDevice("D11565", B)
c = CInt(A)
d = CInt(B)
tt.h=c
tt.i=d
得到的值就像你所说的为35368,请问Tiger_Zhao大哥还可以怎样改?
[其他解释]
如果A为-30168,B为1,合成后的正常值为100904
[其他解释]
终于解决了,谢谢给位大哥的建议
