首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VB >

求高效率的取高字节VB6的函数

2013-04-09 
求高效的取高字节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里由于没有原生提供这个特性,只能绕个大弯了求高效率的取高字节VB6的函数

由于没有任何运算过程,性能当然是最好的.
[解决办法]

好吧,我只是提供一个方案,没想到还被你BS一顿,真是对不起了
[解决办法]
酷心的函数由于全是使用的位运算符,CPU中直接就有相应的数学指令,编译后应该是CPU的直接运算,使用的应该也是CPU的内部缓存.

展开与不展开的区别主要还是在函数调用的开销上,调用函数时涉及到内存的操作的话,内存速度肯定没CPU内部缓存快.

而我的模拟UNION方案主要是内存复制,并未使用运算符,编译后就应该是一堆的MOV指令,完全是基于内存的.

那么这两种方案谁快谁慢是与具体电脑有关的.

如果CPU强大,那么酷心的方案应该会更快.

如果CPU不是很强,但内存频率高的话,就应该是模拟UNION快了.
[解决办法]
求高效率的取高字节VB6的函数

[解决办法]
引用:
获取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
扯远了吧。
要……


这个高效!

热点排行