扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:莫艺潜 来源:天极网 2007年11月4日
关键字: VB
内存地址 | 0 | 1 | …… | 2000 | 2001 | 2002 | 2003 | 2004 | …… | 3070 | …… | 最高编号取决于内存的容量 |
变量实际数据 | 系统保留 | 系统保留 | a | b | c | 70 | 0 | |||||
变量声明 | dim a(2) as byte={a,b,c} | dim b as int32=70 | dim c as byte |
windows标准数据类型 | vb.net数据类型 | 应该申请的字节数组 | 空间占用长度(以字节为单位) |
Byte | Byte | 1 | |
CHAR | Byte | 1 | |
WChar | Char | Dim byt(1) as byte | 2 |
Short | Int16 | Dim byt(1) as byte | 2 |
INT/INT32/LONG/UINT | Int32 | Dim byt(3) as byte | 4 |
DWORD | Int32 | Dim byt(3) as byte | 4 |
Bool | Int32 | Dim byt(3) as byte | 4 |
INT64/LONG64/ULONG64 | Int64 | Dim byt(7) as byte | 8 |
’使用<StructLayout(LayoutKind.Sequential)>属性告诉net编译器:结构的元素在内存中按其出现的顺序排列 <StructLayout(LayoutKind.Sequential)> _ Public Structure DEFUDT_Test Public bytb As Byte Public i32a As Int32 End Structure Public Function fnGetIntptr1() As IntPtr ’取得一个4字节数组指针 Dim tabytTest(3) As Byte ’以下语句告诉net垃圾回收进程不对tabytTest进行处理,也就是说tabytTest占用的内存区域固定不变。 Dim thObject As GCHandle = GCHandle.Alloc(tabytTest, GCHandleType.Pinned) Dim tpObject As IntPtr = thObject.AddrOfPinnedObject() ’取得指向字节数组的指针 ’取得一个指向32位内存数据的指针, ’由于使用gchandle取指针的方法只能对引用的对象有效, ’所以对如int32等值类型必须使用将其封装成为一个对象的方法以变为引用类型 Dim ti32Test As Object = Convert.ToInt32(0) ’以下语句告诉net垃圾回收进程不对ti32test进行处理,也就是说ti32Test的内存位置固定不变。 Dim thObject1 As GCHandle = GCHandle.Alloc(ti32Test, GCHandleType.Pinned) Dim tpObject1 As IntPtr = thObject1.AddrOfPinnedObject() ’取得ti32Test的首地址 Dim tudtTest1 As DEFUDT_Test ’由于结构是一种值类型变量,为保证指针申请方便,我们申请 ’取得一个和结构tudtTest1大小一致的字节数组指针,只要空间占用长度和结构一样就可以了 ’由于net在结构封装中会插入额外的数据位,所以一定要用sizeof方法得到结构在非托管使用时的实际大小 Dim tudtTest(Marshal.SizeOf(tudtTest1)) As Byte Dim thObject2 As GCHandle = GCHandle.Alloc(tudtTest, GCHandleType.Pinned) Dim tpObject2 As IntPtr = thObject2.AddrOfPinnedObject() ’取得指向结构的指针 ’在这儿你可以写对指针处理的任意代码(在例2中会给予补充)…… ’在使用完毕后一定要释放指针指向的内存块,让垃圾回收器可对这个内存块回收处理 If thObject.IsAllocated Then thObject.Free() End If If thObject1.IsAllocated Then thObject1.Free() End If If thObject2.IsAllocated Then thObject2.Free() End If End Function |
Marshal.WriteInt32(tpObject1, 0, Convert.ToInt32(77)) ’向ti32Test变量指向的地址写入32位整数77 MsgBox("现在ti32Test的值为:" & ti32Test) ’因为变量存储地址的数据已改为77,所以显示为77 ’以下这句之所以可行,因为ti32Test是32位整数,而tpObject指向的tabytTest数组刚好有4个元素 ’而每一个byte元素都占用8位,合起来就是32位,和ti32Test占用的空间一样。这就印证了前面提’ ’到的net中指针没有指向类型的说明。 Marshal.WriteInt32(tpObject, 0, ti32Test) ’以下代码再将tabytTest字节数组的内容理解为一个int32整数, ’并将值赋值给tudtTest结构中的int32元素 ’我们使用Marshal.OffsetOf(GetType(DEFUDT_Test), "i32a").ToInt32以取得i32a元素在结构中的内存偏移位置 ’所以New IntPtr(tpObject2.ToInt32 + Marshal.OffsetOf(GetType(DEFUDT_Test), "i32a").ToInt32)就临时产生了 ’一个指针并指向i32a所在的内存地址(, 这个方法也说明了指针可以以字节为单位进行加减计算以指向合适的变量。 ’Marshal.ReadInt32的作用是从指针中读取一个32整数。 Marshal.WriteInt32(New IntPtr(tpObject2.ToInt32 + Marshal.OffsetOf(GetType(DEFUDT_Test), "i32a").ToInt32), _ 0, Marshal.ReadInt32(tpObject)) ’这儿可以将字节数组的内容复制到真正的结构中 MsgBox(Marshal.OffsetOf(tudtTest1.GetType, "i32a").ToInt32) tudtTest1 = CType(Marshal.PtrToStructure(tpObject2, GetType(DEFUDT_Test)), DEFUDT_Test) MsgBox("结构tidtTest1中i32a元素的值为:" & tudtTest1.i32a) ’此处将显示刚赋的值77 |
Public Overloads Sub sbArrayCopy(ByRef ni_aobjArraySource() As Char, ByRef ni_aobjArrayDest() As Byte) ’必要时可以使用重载策略支持任意类型的数组 Dim thObject As GCHandle = GCHandle.Alloc(ni_aobjArraySource, GCHandleType.Pinned) Dim tpObject As IntPtr = thObject.AddrOfPinnedObject() ’取得目标数组的指针 Marshal.Copy(tpObject, ni_aobjArrayDest, 0, ni_aobjArrayDest.Length() - 1) End Sub ’调用语句为: Dim tachrSource() As Char = {"a", "b", "c"} Dim tabytDest(5) As Byte ’2个byte和1个char占用的空间相等 ’以下代码你可以设个断点,然后用快速监视看看tabytDest中的数据内容 sbArrayCopy(tachrSource, tabytDest) ’将tachrSource数组内容复制到tabytDest数组中,注意了类型完全不同哦 |
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者