求高效的取高字节VB6的函数如题,不要使用copymemory函数,效率低。引用:我上面函数和直接调用copymemory??比
求高效的取高字节VB6的函数 如题,不要使用copymemory函数,效率低。
引用: 我上面函数和直接调用copymemory??比,大约快80% copymemory 应该没那么慢的,具体看你的代码是怎么写的?
[解决办法] 取高字节,符号想怎么处理?
[解决办法] 最快就是不经过运算,直接取每个字节的内容,就是C里面的联合体union.
VB里不支持联合体,所以想要使用这个功能得绕点弯,操作SafeArray来实现,但最终效果是一样的.
Option Explicit '仿C语言中的联合体union高效取高低字方法 ' '实现思路: '通过操作SafeArray来使一个数组的pvData指向目标变量,然后直接访问高低字,就像C里面的union一样 ' 'By 嗷嗷叫的老马 'http://www.m5home.com/ Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (ByRef Ptr() As Any) As Long Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _ ByRef Destination As Any, _ ByRef Source As Any, _ ByVal Length As Long) Dim myIntegerArr() As Integer, myLong As Long Dim ppSA As Long, pSA As Long, pvDataOld As Long Private Sub Command1_Click() myLong = &HAABBCCDD '赋值.此变量已与数组"绑定"了. MsgBox Hex(myIntegerArr(0)) & vbCrLf & Hex(myIntegerArr(1)) '直接取得高低字 End Sub Private Sub Form_Load() Call initArray End Sub Private Sub Form_Unload(Cancel As Integer) Call FreeArray End Sub Private Sub initArray() '初始化数组及指针. ' '将SafeArray结构的pvDara指针改为myLong变量的地址,这样就可以直接访问高低字了. ' '简单来说就是"绑定"数组与myLong变量,让它们实际上使用同一个地址,相当于C里面的union ' ReDim myIntegerArr(1) '与要访问的变量的长度相同.这里是要把Long分成两个Integer来访问,那就是0,1两个成员. myLong = VarPtr(myLong) '把自己的地址放在自己里面 ppSA = VarPtrArray(myIntegerArr) '得到指向SafeArray结构指针的指针(有点绕,就是指针的指针...- -!!) Call CopyMemory(pSA, ByVal ppSA, 4) '得到SafeArray指针 MsgBox "pSA=" & Hex(pSA) Call CopyMemory(pvDataOld, ByVal pSA + 12, 4) '保存之前真数组的指针 Call CopyMemory(ByVal pSA + 12, myLong, 4) '设置myLong的指针为真数组指针 End Sub Private Sub FreeArray() '恢复原来申请的真数组指针,并释放数组 ' Call CopyMemory(ByVal pSA + 12, pvDataOld, 4) '恢复myLong的指针为之前申请的真数组指针 Erase myIntegerArr() End Sub
[解决办法] [解决办法] 引用: 支持一下先,不过不是很懂为什么要绕那么多弯?看代码是用MyLong的地址指针替换掉myIntegerArr数组的地址指针,不知道可不可这样 差别很大,HOHO. 我绕那么多弯,目的是让myIntegerArr()与myLong都指向同一个地址,类似C语言中的union. 一旦这一步完成,以后要取myLong的高低字时,直接到myIntegerArr()中取就行了,因为myIntegerArr()中已经就是myLong的内容了,因此除了赋值操作,没有别的操作了. 而你的方法应该就是楼主所说的内存复制法,要调用多次API,虽然API很快,但是调用开销加上执行开销,肯定是比联合体慢得多的.[解决办法] 兴起,做了个测试. 注意,测试全都是编译后的结果.在IDE中我这里申请内存失败了,估计是没那么多的逻辑内存了.把电脑设置为最高性能模式,不做编译优化,结果如下: 生成1亿个LONG随机数=45047ms,提速17% 模拟union方案=1203ms,提速21% zGetLngHigh方案=4469ms,提速27% GetHiWord方案=6531ms,提速44% aGetLongHigh方案=46797ms,提速37% 电脑性能设置为之前的自动,再把编译选项中的高级优化全勾上,结果如下: 生成1亿个LONG随机数=54719ms,降低3% 模拟union方案=1094ms,提速33% zGetLngHigh方案=5281ms,提速7% GetHiWord方案=8015ms,提速17% aGetLongHigh方案=59641ms,提速7% 电脑性能设置为最高性能,再把编译选项中的高级优化全勾上,火力全开了,结果如下: 生成1亿个LONG随机数=41015ms,提速29% 模拟union方案=703ms,提速107% zGetLngHigh方案=4094ms,提速39% GetHiWord方案=5890ms,提速60% aGetLongHigh方案=46515ms,提速37% 有点意思,哈哈. 看来编译优化对于性能的提高还是很明显的啊. 不过对函数的调用几乎就没什么用了,比如生成随机数组时,RND函数是VB6内部已经编译好的,不会再二次编译了,所以没什么效果.------解决方案--------------------
谢谢老马……知道怎么回事了,你的做法是直接让myIntegerArr真数组的地址指向mylong的地址,所以直接对mylong赋值就可以取得了,而我的是copy了mylong的值……[解决办法] 没错. 其实在C语言里就没这么麻烦,因为直接就可以定义union,VB6里由于没有原生提供这个特性,只能绕个大弯了 由于没有任何运算过程,性能当然是最好的.[解决办法] 好吧,我只是提供一个方案,没想到还被你BS一顿,真是对不起了[解决办法] 酷心的函数由于全是使用的位运算符,CPU中直接就有相应的数学指令,编译后应该是CPU的直接运算,使用的应该也是CPU的内部缓存. 展开与不展开的区别主要还是在函数调用的开销上,调用函数时涉及到内存的操作的话,内存速度肯定没CPU内部缓存快. 而我的模拟UNION方案主要是内存复制,并未使用运算符,编译后就应该是一堆的MOV指令,完全是基于内存的. 那么这两种方案谁快谁慢是与具体电脑有关的. 如果CPU强大,那么酷心的方案应该会更快. 如果CPU不是很强,但内存频率高的话,就应该是模拟UNION快了.[解决办法] [解决办法] 引用: 获取Long的高字 Public Function HiWord(ByVal DWord As Long) As Integer HiWord = (DWord And &HFFFF0000) \ &H10000 End Function 扯远了吧。 要满足楼主的要求,仅需非常简单的函数。 再想快一点,直接写表达式,省去函数调用的栈操作。[解决办法] 引用: 引用: 获取Long的高字 Visual Basic code ? 123 Public Function HiWord(ByVal DWord As Long) As Integer HiWord = (DWord And &HFFFF0000) \ &H10000 End Function 扯远了吧。 要…… 可以更简单: Public Function HiWord(ByVal DWord As Long) As Integer HiWord = DWord \H10000 End Function[解决办法] 引用: 可以更简单: Public Function HiWord(ByVal DWord As Long) As Integer HiWord = DWord \H10000 End Function 你以为 Long 是无符号整数啊!用 &HFFFFFFFF 试试,结果多少?------解决方案--------------------
引用: 引用: 获取Long的高字 Visual Basic code ? 123 Public Function HiWord(ByVal DWord As Long) As Integer HiWord = (DWord And &HFFFF0000) \ &H10000 End Function 扯远了吧。 要…… 这个高效!