Type
 
声明用户定义的类型。

语法

Type typename
fieldname1 As DataType
fieldname2 As DataType
As DataType fieldname3 , fieldname4
...
End Type

Type typename [Extends base_typename ] [Field = alignment ]
[Private:|Public:|Protected:]

Declare Sub|Function|Constructor|Destructor|Property|Operator ...
Static variablename As DataType

fieldname As DataType [= initializer ]
fieldname (array dimensions ) As DataType [= initializer ]
fieldname (Any [, Any...]) As DataType
fieldname : bits As DataType [= initializer ]

As DataType fieldname [= initializer ], ...
As DataType fieldname (array dimensions ) [= initializer ], ...
As DataType fieldname (Any [, Any...])
As DataType fieldname : bits [= initializer ], ...

Union
fieldname As DataType
Type
fieldname As DataType
...
End Type
...
End Union

...
End Type

说明

Type用于声明包含一个或多个数据字段的自定义数据类型,包括整数类型,浮点类型,固定大小或可变长度(动态)数组,固定大小或可变长度字符串,位字段或其他用户定义的类型。

类型支持与面向对象编程相关的各种功能:
类型也可能包含嵌套类型或联合,允许根据需要对数据成员进行分组。嵌套类型/联合不允许包含成员过程或静态成员变量(对于本地类型/联合体的限制)。

Memory layout
类型根据本机对齐和填充规则(在Field页面上描述)连续地在内存中排列。当使用文件I / O的类型或与其他程序或编程语言交互时,必须特别小心,以防对齐和填充规则不同。可选的Field = number 说明符可用于更改FreeBASIC方面的行为。

Variable-length data
在FreeBASIC中,类型数据结构最终必须是固定大小的,以便编译器知道为该类型的对象赋值多少内存。不过,类型可能包含可变长度(动态)字符串或数组数据成员。但是,字符串/数组的数据不会直接嵌入到Type中。相反,Type将只包含String/数组描述符结构,FreeBASIC使用后台来管理可变长度的字符串/数组数据。为了在Type中调整数组描述符的结构,一个可变长度(动态)数组数据成员必须始终通过使用Any(S)代替数组边界来声明,以便根据数字来修正维度量的Anys指定。

因此,将这样的类型保存到文件中将写出描述符,而不是实际的字符串/数组数据。为了将字符串/数组直接嵌入到类型中,必须使用固定长度的字符串/数组。

类似地,当通过使用类型中的指针来手动维护动态数据时,将类型保存到文件通常没有意义,因为存储在指针字段中的地址将被写入文件,而不是其指向的实际内存至。地址对特定进程而言是有意义的,但不能以这种方式共享。

Special note on fixed-length strings
目前,String * N 类型的固定长度字符串字段在其结尾处有一个额外的空终止符,用于与C字符串兼容,使得它们与Types中的QB字符串不兼容,因为它们实际上使用了N +1个字节,而不是N个字节。一个可能的解决方法是声明字段As String * (N -1),尽管如果空终止符被删除,这将不会在将来的版本中运行。另一个选择是使用适当大小的ByteUByte数组。

例子

这是QB样式类型的示例,不包括过程定义
Type clr
    red As UByte
    green As UByte
    blue As UByte
End Type

Dim c As clr
c.red = 255
c.green = 128
c.blue = 64


这是一个作为对象工作的类型的例子:
''显示UDT中固定长度字符串字段的问题示例
''假设我们从文件中读取了GIF标题
''签名宽度高度
Dim As ZString*(10+1) z => "GIF89a" + MKShort(10) + MKShort(11)

Print "使用固定长度的字符串"

Type hdr1 Field = 1
   As String*(6-1) sig /'我们必须使用1个字符来维度字符串
                     '  less to avoid misalignments '/
   As UShort wid, hei
End Type

Dim As hdr1 Ptr h1 = CPtr(hdr1 Ptr, @z)
Print h1->sig, h1->wid, h1->hei ''打印GIF89(错过一个char!)10 11

''我们只能使用5个可见的字符进行比较,并用LEFT创建一个临时字符串

If Left(h1->sig, 5) = "GIF89" Then Print "ok" Else Print "错误"


''使用ubyte数组,我们需要一个辅助函数将其转换为字符串
Function ub2str( ub() As UByte ) As String
    Dim As String res = Space(UBound(ub) - LBound(ub) + 1)
    For i As Integer = LBound(ub) To UBound(ub)
        res[i - LBound(ub)] = ub(i)
    Next
    Function = res
End Function


Print
Print "使用一组ubytes"

Type hdr2 Field = 1
   sig(0 To 6-1) As UByte ''尺寸6
   As UShort wid, hei
End Type

Dim As hdr2 Ptr h2 = CPtr(hdr2 Ptr, @z)
''查看和比较是正确的,但需要转换为字符串

Print ub2str(h2->sig()), h2->wid, h2->hei ''打印GIF89a 10 11(好的)
If ub2str(h2->sig()) = "GIF89a" Then Print "ok" Else Print "错误" ''打印好的


平台差异

  • DOS和Linux目标的默认领域对齐参数为4字节。
  • 对于Windows目标,默认领域对齐参数为8个字节(对于4个字节的差异仅适用于Longint和Double成员)。

方言差异

  • 与{99796001}类型块中声明的功能相关的对象相关功能仅在版本0.17b时才支持-lang fb 方言
  • -lang fb -lang fblite 方言中,默认领域对齐参数取决于目标平台。
  • 除非另有规定,否则使用-lang qb 方言,字段默认与字节边界对齐。
  • 要强制使用字节对齐FIELD = 1 .

与QB差别

  • 目前,固定长度字符串在结尾有一个额外的冗余字符,这意味着它们比QB中占用多一个字节。因此,使用它们的UDT在用于文件I / O时与QB不兼容。

参考