VB6中的指针位移运算——无符号长整数加减法的实现

本文探讨了在VB6中使用Long类型表示无符号整数(指针)时遇到的溢出问题,以及如何实现无符号整数的加减法。文章通过分析不同类型的溢出,提出了一个简单的但存在缺陷的算法,并给出了一个较为完备的算法,该算法能处理可能的溢出并适用于无符号整数的减法。
摘要由CSDN通过智能技术生成

版权声明:可以任意转载,转载时请务必以超链接形式标明如下文章原始出处和作者信息及本声明

作者:xixi

出处:http://blog.csdn.net/slowgrace/archive/2009/04/27/4130448.aspx

本文来自这个帖子的讨论,感谢Tiger_ZhaoSoyokazeunsignedChen8013等的指点。

API函数中常常需要用到指针(内存地址)参数,这通常对应为C中的unsigned int类型。unsigned int为32位无符号整数,用于表示逻辑内存可达4G[0,232-1]。在VB中没有无符号整数这种类型,通常会把指针声明为long类型,这是一种32位有符号整数,取值范围是[2-31,231-1]。这种差别,有时会导致在VB6中计算指针位移的时候溢出或得到错误的计算结果,因此,有必要采用特别的算法来实现无符号整形的加减法。

1、几种不同的溢出

1.1. Long和Unsigned在坐标轴上的"4G"关系

Long和Unsigned都是32位整数,因此它们的十六进制表示“范围”是基本一致的,都是从0到&HFFFF FFFF。所不同的是,在VB中,负整数是以补码表示的,符号位在最高位(0表示正数,1表示负数)。因而,在VB中大于7FFF FFFF的十六进制数实际上都被理解为负数,包括从&H8000 0000到&HFFFF FFFF的数。因而,long型和unsigned int的取值范围在坐标上的位置错了231个单位长度,如下图:

LONG & UNSIGNED 

其中,unsigned从231-1到232-1区间内的数和Long从-231到0区间内的数的十六进制表示完全一样,但对应的十进制数值差232,对于32位地址空间来说,可以认为它们等价,即(“==”表示“等价于”):

[&H80000000, &HFFFFFFFF]long==[-231, -1]10进制

[&H80000000, &HFFFFFFFF]unsigned==[231, 232-1]10进制

我们不妨称这种现象为4G取模等价性或简称4G等价性。为便于讨论,我们先定义几种不同的溢出:

1.2. unsigned溢出

如果一个数大于4G(以下我们用4G代表2^32,2G代表2^31)或者小于0,对于Unsigned类型就是溢出了,这个我们不妨称为超越unsigned边界,或称unsigned溢出。考虑两个指针的运算,由于unsigned只能表达4G的逻辑内存,当指针运算结果出现unsigned溢出时,根据不同的编程需求,我们通常会对函数有两种期待。一种是,希望负责运算的函数报告溢出、以防止异常的内存操作,不妨称这种处理方法叫直接溢出(不妨简称溢出法);另一种是希望它取模不溢出(不妨简称取模法),也就是:

  a)如果两个无符号整数i和j的和sum超过4G,那么我们希望这时或者希望这个结果指针指到sum mod 4G的位置,也就是sum-4G的位置。假设i>j,就有:

i+j==i+j-4G==i+(j-4G)==i+与j对应的有符号负整数

也即,我们希望指针算法,在计算两个和超过4G的指针加法时,能够把它转换为减法(1个正数与1个负数的加法),而不是溢出。

  b)同样,如果两个无符号整数i和j的差sub小于0,我们也希望这个结果指针指到sub mod 4G的位置,也就是sub+4G的位置。假设i<j,就有:

i-j==i-j+4G==i-(j-4G)==i+与j对应的有符号负整数

也即,我们希望指针算法,在计算两个差小于0的指针减法时,能够把它转换为加法(1个正数与1个负数的加法),而不是溢出。

只要一个指针算法能对所有的unsigned溢出都能始终如一地坚持其中一种处理方法(直接溢出或取模不溢出),我们就可以认为它是一个正确的算法。

1.3. long溢出

如果一个数小于-2G,或者大于2G-1,对于long类型就是溢出了,我们不妨称这个数字long越界,这种溢出为long溢出。因为本文主要讨论在VB中实现指针运算,所以long溢出才是我们要集中精力对付的溢出。值得注意的是,由于负整数的补码表示,当我们以十六进制表示的大于&H7FFFFFFF的大正数送到VB程序里时,并不会溢出,而只是被理解为一个负整数。只有当你以十进制来表示一个long越界的数字并赋给long型变量时,或计算结果long越界时,才会产生long溢出。

1.4. VB6中指针运算时可能出现的溢出

考虑在VB中进行指针位移的各种情况。假设有两个无符号整数uintA, uintB,考虑VB中如下代码的可能后果

Dim uintA As Long, uintB As Long
Dim</
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值