讨论VB中的结构体

讨论VB中的结构体[转载]
2009年10月20日 星期二 11:30


VB里面的结构体是一种WORD/DWORD对齐的结构体,这一点在编程中尤其要注意,如果是纯VB编程,则结构体的各个域如何排列可以基本不用关心,
而如果是调用API或者是调用其他的动态链接库,则很容易出问题,原因就在于:这些动态链接库是用C/C++写的,而大部分C/C++环境里的
结构体是非DWORD对齐的。这就导致调用动态链接库的时候,如果传一个结构体给一个动态链接库的接口函数,可能会导致不期望的结果;

经过实验,发现VB里面结构体的DWROD规则如下:

如果结构体里面类型最大的域的字节数大于等于4个字节:
1.结构体变量的起始地址必须是4的整数倍;
2.结构体的每个域的起始地址必须是4的整数倍;(如果需要,通过在前一个域的末尾补占位字节来达到该目的)
3.结构体的总的字节数必须是4的整数倍;(不够的话,在末尾补占位字节)

如果结构体里面类型最大的域的字节数等于2个字节(就是说最大的类型才是integer):
1.结构体变量的起始地址必须是2的整数倍;
2.结构体的每个域的起始地址必须是2的整数倍;(如果需要,通过在前一个域的末尾补占位字节来达到该目的)
3.结构体的总的字节数必须是2的整数倍;(不够的话,在末尾补占位字节)

如果结构体里面类型最大的域的字节数等于1个字节(就是说最大的类型才是Byte):
没有DWORD对齐规则,所有的域紧凑的排列,每个域紧密连在一起;也就是说:有几个域就有几个字节;


实验用代码如下,通过该代码可以清楚的窥探到VB结构体的存储规则:
-----------------------------------------------------
Option Explicit

Private Type aaa
f As Byte
g As Byte
x As Byte
y As Byte
z As Byte
a As Double
b As Integer
c As Byte
d As Byte
e As Byte
End Type


Private Type bbb
a As Byte
b As Integer
c As Byte
End Type

Private Type ccc
a As Byte
b As Double
End Type

Private Type ddd
a As Byte
b As Byte
e As Byte
f As Byte
g As Byte
End Type


Private Sub Command1_Click()
Dim s As aaa
MsgBox LenB(s)
MsgBox VarPtr(s) Mod 4
End Sub

Private Sub Command2_Click()
Dim x As bbb

MsgBox LenB(x)
MsgBox VarPtr(x) Mod 4

End Sub

Private Sub Command3_Click()
Dim x As ccc
MsgBox LenB(x)
End Sub

Private Sub Command4_Click()
Dim x As ddd
MsgBox LenB(x)
MsgBox VarPtr(x)
End Sub
-----------------------------------------------------

根据这个规则,会发现有时候声明同样的一个结构体,仅仅由于各个域的次序不同,就会导致结构体占用的空间大小不同的现象,
这也可用作一个程序优化技巧,减少程序的内存占用率;

例如:
Private Type bbb
a As Byte
b As Integer
c As Byte
End Type

Private Type bbb
a As Byte
c As Byte
b As Integer
End Type

两种声明方式完成的目的一样,但占用的内存空间是不一样的,显然后者会更节约内存;


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/qiqi5521/archive/2006/06/23/826040.aspx

相关文章

Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强制返回为文本 --------------------------...
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办法, Format 或者FormatDateTime 竟然结果和...
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace My ‘全局错误处理,新的解决方案直接...
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用的爽呀,这篇文章写与2011年,看来我以前没...
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选中的单元格进行处理 Dim m As Range, t...
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integ...