FreeBASIC マニュアルのトップに戻る

FreeBASIC Type (UDT)

目次→言語リファレンス→変数とデータ型→ユーザ定義型TYPE (UDT)←オリジナル・サイト

TYPE (UDT) 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

ユーザ定義の型を、宣言します。

構文:
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
Redim arrayname(array dimensions) 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 は、1つか複数のデータ項目を含む、カスタム・データ型を宣言するために使われます。
整数型、浮動小数点型、固定長か可変長(動的)の配列、固定長か可変長の文字列、ビット項目、あるいは他のユーザー定義型を含めることができます。

Type は、オブジェクト指向プログラミングと関係する様々な機能性をサポートします:

Type には、さまざまな種類の入れ子にされた typeunion(共用体) を含めることができます:
主構造体(Type または Union)は常に名前を付ける必要があり、他の (入れ子にされた) 構造は無名または名前付きにすることができます。

Alias "alternatename" は、typename を(オブジェクト・モジュールやライブラリのように)パブリック・シンボルにエンコード(修飾)する必要がある場合、typename の通常のエンコード(修飾)の代わりに、alternate 名を使います。


メモリ・レイアウト
Type は、Type の項目を、メモリに連続的に配置します。固有の整列と詰め物の規則( Field ページに記述) に従います。
Type を、ファイルI/Oに使う場合や、他のプログラムやプログラミング言語と対話するとき、特別に注意しなければなりません。整列と詰め物の規則が異なることがあるからです。
オプションの Field = number 指定子を使うと、FreeBASIC 側の振る舞いを変更できます。

可変長データ
FreeBASIC では、型データ構造は、最終的に固定サイズでなければなりません。コンパイラが、どれだけのメモリをその型の対象に割り当てるかわかっている必要があるからです。
それでも、型は可変長(動的)文字列や配列データ・メンバーを含むかもしれません。
しかし、文字列/配列のデータは、型に直接埋められません。
その代わり、Type は、String/配列記述構造を含むだけです。 そして、FreeBASIC は、この記述構造を、可変長文字列/配列データを管理するために裏側で使います。
Type (型)の配列記述子の構造をサイズ設定するために、可変長(動的)配列データメンバは、常に配列の範囲のところに Any(s) を使って宣言する必要があり、指定された Any の数に基づいて次元の量を固定します。
可変長(動的)配列のデータメンバーは、Redim を使った構文で宣言時にサイズをあらかじめ指定することもできます。
可変長の配列フィールドは、可変長の文字列と同様に、Type で宣言されると、疑似オブジェクトとみなされます(暗黙のコピー構築子と暗黙の let 演算子自体が、このような配列の[再]サイジングとコピー、およびその消去をサポートします)。

このため、そのような Type をファイルに保存するには、実際の文字列/配列データではなく、記述子を書きます。
文字列/配列を、Type に直接埋め込むためには、固定長文字列/配列を使わなければなりません。

同様に、Type の中でポインターを使って、手で動的なデータを維持するとき、ファイルに Type を保存することは、通常意味をなしません。ポインターが指す実際のメモリではなく、ポインター項目に格納されるアドレスが、ファイルに書かれるからです。
アドレスは、特定のプロセスにのみ意味があります。そのように共有されることができません。

固定長文字列の特別な注意
fbc バージョン 1.20.0 以降、String * N 型の固定長文字列フィールドは、末尾に余分な null ターミネータがなくなり、実際に使うのは N バイトだけなので、型内の QB 文字列と互換性を持つようになりました。
fbc バージョン 1.20.0 より前は、String * N 型の固定長文字列フィールドには、C 文字列との互換性を保つために末尾に余分な null 終端文字があり、ちょうど N バイトではなく、実際に N+1バイトを使うため、型内の QB 文字列と互換性がありませんでした。 考えられる回避策は、フィールドを As String * (N-1) と宣言することでした。ただし、これは、将来のリリースで null 終端文字が削除されると機能しなくなります。 もう 1 つの方法は、適切なサイズの ByteUByte 配列を使うことです。

bitfields ( fieldname : bits ) の注意
ビット項目は、TypeUnion(共用体)の内部だけで宣言され、ビット長の数で与えられる、非常に小さなオブジェクトを指定できるようにすることができます。
各項目は、アクセスされて、それが構造体の通常の一員であるかのように操作されます。
整数データ型(32ビット開発では最大32ビット、64ビット開発では最大64ビット)のみ、有効です。
宣言データ型のサイズは、ビットパターンを含むのに十分な大きさで、メモリにビット項目を配置される方法に影響します。
型内のビット項目メンバーは、次のメンバーが非ビット項目でない限り、一緒にパックされます(ネストされたユニオンは非ビット項目と見なされます)。
ビット項目にはアドレスがありません(構造内で、ビット項目へのポインタと、そのオフセットを取得することはできません)。

例:
下は、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 の固定長文字列項目と fbc バージョン < 1.20.0 の問題を示す例
'' ファイルから、GIFヘッダーを読みます
''                        signature         width        height
Dim As ZString*(10+1) z => "GIF89a" + MKShort(10) + MKShort(11)

Print "Using fixed-length string"

Type hdr1 Field = 1
   #if __FB_VERSION__ < "1.20.0"
      As String*(6-1) sig /' ミスアライメント(不整列)を回避するため、
                        '  1文字少ない文字列を指定する必要があります '/
   #else
      As String*(6) sig
   #endif
   As UShort wid, hei
End Type

Dim As hdr1 Ptr h1 = CPtr(hdr1 Ptr, @z)
Print h1->sig, h1->wid, h1->hei '' Prints GIF89 (misses a char!)  10  11

'' 見える5文字と、LEFT で切り取った一時的な文字列を比較します

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


'' 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 '' Dimension 6
   As UShort wid, hei
End Type

Dim As hdr2 Ptr h2 = CPtr(hdr2 Ptr, @z)
'' 見たり比較したりは、正しくできます。しかし、文字列への変換が必要です

Print ub2str(h2->sig()), h2->wid, h2->hei '' Prints GIF89a  10  11 (ok)
If ub2str(h2->sig()) = "GIF89a" Then Print "ok" Else Print "error" '' Prints ok
Sleep


これは、ローカル UDT のビット項目を使って、Ubyte から、ベース8(8進数文字列)の数文字列に変換する例です
('Oct(x, 3)' と同じ変換です):
Function UbyteToOctalString (ByVal b As UByte) As String
 
    Union UbyteOctal
        number As UByte
        Type
            d0 : 3 As UByte
            d1 : 3 As UByte
            d2 : 2 As UByte
        End Type
    End Union
 
    Dim uo As UbyteOctal
    uo.number = b
    Return uo.d2 & uo.d1 & uo.d0
 
End Function


For I As Integer = 0 To 255
    Print Using "###: "; I;
''    Print Oct(I, 3),
    Print UbyteToOctalString(I),  '' この行は、前のものと、等価です
Next I
Print

Sleep


これは、ネストされた名前付き型の例です:
Type Parent
    Private:
        Dim As String nameParent
        Declare Constructor()
        Declare Constructor(ByRef As Parent)
        Type Child
            Dim As String nameChild
            Dim As Parent Ptr ptrParent
            Declare Sub kinship()
        End Type
        Dim As Child listChild(Any)
    Public:
        Declare Constructor(ByRef _nameParent As String)
        Declare Sub addChild(ByRef _nameChild As String)
        Declare Sub kinship()
End Type

Constructor Parent(ByRef _nameParent As String)
    This.nameParent = _nameParent
End Constructor

Sub Parent.addChild(ByRef _nameChild As String)
    ReDim Preserve This.listChild(UBound(This.listChild) + 1)
    This.listChild(UBound(This.listChild)).nameChild = _nameChild
    This.listChild(UBound(This.listChild)).ptrParent = @This
End Sub

Sub Parent.Child.kinship()
    Print "'" & This.nameChild & "'" & " is child of " & "'" & This.ptrParent->nameParent & "'"
End Sub

Sub Parent.kinship()
    For i As Integer = 0 To UBound(This.listChild)
        This.listChild(i).kinship()
    Next i
End Sub


Dim As Parent p = Parent("Kennedy")
p.addChild("John Jr.")
p.addChild("Caroline")
p.addChild("Patrick")
p.kinship()

Sleep

バージョン:
プラットホーム差: 方言差: QBからの違い: 参照:
ユーザ定義型 に戻る
←リンク元に戻る プログラム開発関連に戻る
ページ歴史:2024-03-07 06:08:57
日本語翻訳:WATANABE Makoto、原文著作者:SysOp

ホームページのトップに戻る

表示-非営利-継承