月刊プログラム!
構造体

2001.May.30


修正
2003.02.14 内容をちょい修正
何者か

ストレートに言うと「単体もしくは複数の要素(メンバ)を持ったユーザー定義の型」です。
つまり1個の変数を構造体として宣言すれば、その変数は(宣言した数だけ)複数の値を持つ事ができます。
これは重宝しますよ。

宣言

構造体の宣言の仕方です。
宣言する場所は全てのプロージャの外にしなくてはなりません。


' 構造体の宣言は Type ステートメントを使う
Type MyStruct
    Name As String
    Age  As Integer
End Type
          


TypeEnd Typeの中に、変数を宣言するように、構造体のメンバ(要素)を宣言します。
しかし変数を宣言しているのはありません。
「型」そのものを宣言していると考えてください。

上の例では「MyStruct」という構造体(型)を宣言しました。
この構造体を実際に使用する場合は、

Dim Status As MyStruct

とし、Status 変数を MyStruct 型として宣言します。

では、どうやって使うのか?
上の例の場合、MyStructは2つのメンバを持っています。
「Name」と「Age」です。
実際にこれらのメンバにアクセスする場合は「Statusの中のName」とか「Statusの中のAge」といった考えでOKです。

んじゃ次に、この構造体を使ったサンプルコードを作ってみましょう。

' モジュールレベル(グローバル領域)で宣言
' プロージャレベルでは宣言出来ない

' 構造体の宣言(ユーザー定義型とも言う)
Type MyStruct
    Name As String   ' 筆者は As から型の位置を揃えるクセがあります
    Age  As Integer
End Type



Sub Sample() ' MyStruct型の変数の宣言 Dim Status As MyStruct '値の代入 Status.Name = "たろ" Status.Age = 22 'シートに反映 Cells(1, 1).Value = "名前は" Cells(2, 1).Value = "歳は" Cells(1, 2).Value = Status.Name Cells(2, 2).Value = Status.Age End Sub


実行結果


こんな感じですね。
これ書いてる現在は筆者は22歳です。
若いです。
関係ありませんね。


構造体は覚えとけ!

構造体もマスターすれば、かなり強力な武器になります。
と同時に、後々に大きなプログラムを作っていくうちに必須なものとなりえます。
かなり便利なものなので、覚えておきましょう。
(それに使いこなせると楽しいですし)
構造体あれこれ(メモリ配置など)

構造体のメンバは配列と同じく、宣言した順に空きメモリへ順番に割り当てられます。
例えば、

Type MyStruct
    aaa As Integer
    bbb As Byte
    ccc As Long
    ddd As String
    eee As Boolean
End Type

という構造体を宣言したのなら、メモリへの配置は、


という感じになります。
宣言したメンバが順番に配置されている点に注意してください。
さらにこれを証明付けるコードを組んでみます。


Sub Sample()
Dim var As MyStruct

' アドレスとメンバの型の領域を表示
Debug.Print VarPtr(var.aaa); Len(var.aaa)
Debug.Print VarPtr(var.bbb); Len(var.bbb)
Debug.Print VarPtr(var.ccc); Len(var.ccc)
Debug.Print VarPtr(var.ddd); Len(var.ddd)
Debug.Print VarPtr(var.eee); Len(var.eee)

End Sub

Debug.Printとは、イミディエイトウィンドウへ処理結果を表示できる便利なデバッグの技です。
イミディエイトウィンドウは「表示(V)」メニューから「イミディエイトウィンドウ(I)」を選びます。
VarPtr関数については以前もやりました。変数のアドレスを返すVBの隠し関数です。
Len関数はそのメンバが使用する型サイズを調べています。
実行結果

6485332 2
6485334 1
6485336 4
6485340 0
6485344 2

上のメモリマップの「A1」番地を6485332番地と考えれば、上で示したメモリ配置は正しいと証明できました。(メモリ内のどこへ配置されるかはメモリの使用状により変動します)

あれ?メンバdddのサイズが0ですぜ?

えーと、これは文字列型だからです。
Len関数はもともと「文字列の長さを取得する」ものであり、こういう使い方では文字列型の型サイズを求めることはできません。
Len関数に文字列型変数を渡すと、型サイズではなく文字の長さを調べてしまうからです。
今回はこのメンバに文字列の代入はしてませんので、0でいいのです。

んで、文字列型の型サイズというのは、今のWin32と呼ばれるOSでは32ビット、つまり4バイトとなります。
これはポインタの型サイズと同じです。
この辺の知識は少し上級者向けですので、ここでは詳しい説明は省きます。


※訂正
上記の説明ですが、Win32での構造体の場合、メモリへの配置は連続して配置されるとは限りません。
これは「アライメント」と呼ばれ、各メンバは「4バイト境界」へ置かれます。
しかし必ずしも4バイト毎に置かれるかといったらそうでもなく、メンバの一番大きい型に合わせてその前後のメンバに影響があるようです。(VBの仕様?)
構造体自体のサイズは、その「埋め」のサイズは省かれますし、考え方としては一見正しいですが、説明が少し不備でした。

終わり

構造体でした。
最後のメモリ配置のされかたなどは、少し蛇足でしたが、大体基本はこんなとこです。
あと、メンバには配列、さらに構造体(構造体の中にまた構造体)といった宣言もできます。
いろいろ試してみてください。

終わり



[先頭ページへ] [次のページへ]

リンクフリー  Copyright (C) K_Yaguchi