| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1068 人关注过本帖, 1 人收藏
标题:VB指针教程2--2010.5.14.14.07更新
只看楼主 加入收藏
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
结帖率:78.95%
收藏(1)
 问题点数:0 回复次数:8 
VB指针教程2--2010.5.14.14.07更新
上一节教程链接:https://bbs.bccn.net/thread-305122-1-1.html
演示工程源码:
demo3.zip (33.3 KB)

程序代码:
'我们先理解一下数组的概念,数组是由一组连续的内存区域构成
'比如有一排连续的房间,每个房间都有一个编号,这个编号也是连续的。
'例如房间1、房间2、...房间n,这个n就是房间的编号,如果我对你说“请”到房间2
'拿一本书给我,那么你完成这个任务首先就是找到房间2,然后进入房间2拿到这本书。
'显而易见这个编号实际上就是地址
'那么,如果我们取得数组的首地址,那么我们就可以根据地址对数组进行各种操作。
'C语言提供了取得数组地址的语言特性,而VB则没有这样的语言特性,但我们依然可以
'通过API得到数组的地址。我们先来认识下这一个DLL--Msvbvm60.dll,这个是vb6.0
'的程序运行库,其就提供了一个可以获得数组地址的API,它的api声明如下:
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" _
        (ptr() As Any) As Long
       
'CopyMemory API请参照《VB指针教程1》,地址:https://bbs.bccn.net/thread-305122-1-1.html
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
       (Destination As Any, Source As Any, ByVal Length As Long)

Private Sub Form_Load()
    Dim arr(1 To 3) As Integer
    For i = 1 To 3
        arr(i) = i * 10
    Next
    Dim arraddr As Long
    '取得arr数组的首地址
    arraddr = VarPtrArray(arr)
    Dim arr1 As Integer, arr2 As Integer, arr3 As Integer
    CopyMemory arr1, ByVal arraddr, 2
    CopyMemory arr2, ByVal arraddr + 2, 2
    CopyMemory arr3, ByVal arraddr + 4, 2
    List1.AddItem "arr(1)=" & arr1
    List1.AddItem "arr(2)=" & arr2
    List1.AddItem "arr(3)=" & arr3
End Sub
'观察运行的结果,显然不是我们所预期的,为什么呢?这是因为VB数组的存储结构不同于我们先前所说的。
'VB数组的存储结构是使用一种叫做SafeArray的结构,而VarPtrArray(arr)取得的即是指向SafeArray结
'构的指针 ,我们现在得先去了解下SafeArray结构:
'Private Type SafeArray
'    cDims As Integer     '指向数组维数的指针
'    fFeatures As Integer '用来描述数组如何分配和如何被释放的标志
'    cbElements As Long   '指向数组元素所占的字节数的指针
'    cLocks As Long       '一个计数器,用来跟踪该数组被锁定的次数
'    pvData As Long       '指向数组内一个元素的指针,最重要的部分
'    cElements As Long    '数组元素的个数
'    lLbound As Long      '数组的下限
'End Type
''以下是fFeatures的常量标志
'Private Const FADF_AUTO         As Integer = &H1   '在堆栈中执行的分配
'Private Const FADF_STATIC       As Integer = &H2   '静态分配
'Private Const FADF_EMBEDDED     As Integer = &H4   '在结构中创建
'Private Const FADF_FIXEDSIZE   As Integer = &H10   '不能改变数组大小
'Private Const FADF_RECORD      As Integer = &H20   '记录容器
'Private Const FADF_HAVEIID     As Integer = &H40   '有IID 身份标记 数组
'Private Const FADF_HAVEVARTYPE As Integer = &H80   'VT 类型数组
'Private Const FADF_BSTR       As Integer = &H100   'BSTR数组
'Private Const FADF_UNKNOWN    As Integer = &H200   'IUnknown* 数组
'Private Const FADF_DISPATCH   As Integer = &H400   'IDispatch* 数组
'Private Const FADF_VARIANT    As Integer = &H800   'VARIANTs数组
'Private Const FADF_RESERVED  As Integer = &HF008   '余留,将来使用
  
Private Sub Command1_Click()
   List2.Clear
   List3.Clear
   Dim arr(1 To 3) As Integer
   For i = 1 To 3
       arr(i) = i * 10
   Next
   '指向SafeArrayld结构的指针
   Dim SafeArrayldPoint As Long
  
   '把arr数组的首地址复制到SafeArrayldPoint
   CopyMemory SafeArrayldPoint, ByVal VarPtrArray(arr), 4
  
   '数组的维数
   Dim dims As Integer
   CopyMemory dims, ByVal SafeArrayldPoint, 2
   List2.AddItem "数组的维数:" & dims
  
   Dim elements As Long
   CopyMemory elements, ByVal SafeArrayldPoint + 4, 4
   List2.AddItem "数组元素所占的字节数:" & elements
  
   Dim eCount As Long
   CopyMemory eCount, ByVal SafeArrayldPoint + 16, 4
   List2.AddItem "数组元素的个数:" & eCount

 
   Dim lBd As Long
   CopyMemory lBd, ByVal SafeArrayldPoint + 20, 4
   List2.AddItem "数组的下限:" & lBd
  
  '读取数组的值
   Dim arraddr As Long
   CopyMemory arraddr, ByVal SafeArrayldPoint + 12, 4
   Dim arr1 As Integer, arr2 As Integer, arr3 As Integer
   CopyMemory arr1, ByVal arraddr, 2
   CopyMemory arr2, ByVal arraddr + 2, 2
   CopyMemory arr3, ByVal arraddr + 4, 2
   List3.AddItem "arr(1)=" & arr1
   List3.AddItem "arr(2)=" & arr2
   List3.AddItem "arr(3)=" & arr3
   '修改数组的值
   CopyMemory ByVal arraddr, 13, 2
   CopyMemory ByVal arraddr + 2, 28, 2
   MsgBox "arr(1)=" & arr(1)
   MsgBox "arr(2)=" & arr(2)
   MsgBox "arr(3)=" & arr(3)
End Sub

演示工程界面:
图片附件: 游客没有浏览图片的权限,请 登录注册


[ 本帖最后由 ioriliao 于 2010-5-4 16:24 编辑 ]
搜索更多相关主题的帖子: 指针 教程 
2010-05-03 15:14
wei855198
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:5
帖 子:228
专家分:944
注 册:2009-4-24
收藏
得分:0 
决定关注并学习

护肤小店 http://mina2010.
靓装小店 http://liangliyizu2010.
2010-05-03 20:23
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 
谢谢支持。

/images/2011/147787/2011051411021524.jpg" border="0" />
2010-05-03 22:38
jiashie
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:237
专家分:999
注 册:2009-4-30
收藏
得分:0 
顶。
2010.5.14.14.07更新

难道我穿越了?

另外,如果单纯只是读取数组中的值,而不需要读取数组的维数 等信息的话,可以不用考虑SafeArray结构,直接copymemory就ok了吧。不过在实际应用中常常是读取结构体的值(内存对齐的问题)而读取数组的值相对较简单
Dim i As Integer
Dim arr(1 To 3) As Integer
For i = 1 To 3
    arr(i) = i * 10
Next
Dim arraddr As Long
arraddr = VarPtr(arr(1))    '数组首地址也就是第一个元素的地址,学过C的都知道
Dim arr1 As Integer
Dim arr2 As Integer
Dim arr3 As Integer
'注意byval 与不加byval
CopyMemory arr1, ByVal arraddr, 2        'CopyMemory arr1, arr(1), 2
CopyMemory arr2, ByVal arraddr + 2, 2    'CopyMemory arr2, arr(2), 2
CopyMemory arr3, ByVal arraddr + 4, 2    'CopyMemory arr3, arr(3), 2
Debug.Print arr1, arr2, arr3
2010-05-05 09:48
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:0 
我一般用 CopyMemory  来进行 数据格式强制转化。
如 byte(1 to 4) 转为 long

这种转换在 处理流数据中通常需要使用。

授人于鱼,不如授人于渔
早已停用QQ了
2010-05-05 10:07
nbaqqqq
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:202
专家分:137
注 册:2009-11-6
收藏
得分:0 
收藏好,顶起。
2010-05-05 10:10
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 
回复 4楼 jiashie
原来我的coms没电了,难怪会穿越。。。呵呵。。。

/images/2011/147787/2011051411021524.jpg" border="0" />
2010-05-05 10:36
我爱你们
该用户已被删除
收藏
得分:0 
提示: 作者被禁止或删除 内容自动屏蔽
2010-05-05 11:17
Joforn
Rank: 6Rank: 6
等 级:贵宾
威 望:23
帖 子:1242
专家分:122
注 册:2007-1-2
收藏
得分:0 
回帖,就想看下自己有多少专家分

VB QQ群:47715789
2010-05-05 22:40
快速回复:VB指针教程2--2010.5.14.14.07更新
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.041840 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved