VB2005での構造体について

解決


さらん  2007-09-27 22:42:37  No: 99479

教えて下さい。
VB2005の超初心者です…。

Structure INFO2
    Dim a2         As Integer
End Structure

Structure INFO1
    Dim a1         As Integer
    Dim i2         As INFO2
End Structure

Dim i1    as INFO1

上のような構造体を宣言しました。
で、Len(i1)で構造体のサイズを取得しようとしたのですが
返ってきた答えは4…。
VB6ではちゃんと8が返ってきたはずなんです。
どのようにすればいいのでしょうか?

よろしくお願いします…。


魔界の仮面弁士  2007-09-27 22:57:54  No: 99480

> 返ってきた答えは4…。
> VB6ではちゃんと8が返ってきたはずなんです。

あれ? 当方の VB2005 では「8」が返されましたよ。

Public Class Form1
  Structure INFO2
    Dim a2 As Integer
  End Structure

  Structure INFO1
    Dim a1 As Integer
    Dim i2 As INFO2
  End Structure

  Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    Dim i1 As INFO1
    MsgBox(Len(i1))
  End Sub
End Class

> どのようにすればいいのでしょうか?
Len 関数で良いと思いますが、他の方法ということであれば、
Marshal クラスの SizeOf メソッドでサイズを得られます。

ただし、(VB6 で、Len と LenB の結果が異なる場合があったように)
Len と Marshal.SizeOf とで、結果が異なることがある点にはご注意を。

もし、そうしたメンバ間のパディングの扱いまで考慮する必要が
あるのなら、StructLayoutAttribute 属性の併用を検討してみてください。


さらん  2007-09-27 23:08:48  No: 99481

すいません。
自分が出した例ではちゃんとなりますね…。

Structure INFO2
    Dim a2         As Integer
End Structure

Structure INFO1
    Dim a1         As Integer
    <VBFixedArray (  3)> Dim i2()     As INFO2
End Structure

Dim i1    as INFO1

です。
お手間かけましたがよろしくお願いします…。


魔界の仮面弁士  2007-09-28 00:17:17  No: 99482

> 自分が出した例ではちゃんとなりますね…。
で、新しい例の場合には、どのような値が欲しいのでしょうか?
また、それらの構造体を、どのように利用されるのでしょうか?
それによって、適切な対処方法も変わってくるかと。

> お手間かけましたがよろしくお願いします…。
先に回答した Marshal クラス等では、目的を果たせませんか?

Imports System.Runtime.InteropServices
Module Module1
    Structure INFO1
        Dim a As Integer
    End Structure

    Structure INFO2
        Dim a As Integer
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> Dim b() As INFO1
    End Structure

    Structure INFO3
        Dim a As Integer
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> Dim b() As Integer
    End Structure

    Sub Main()
        Dim x As INFO2, y As INFO3
        ReDim x.b(3), y.b(3)
        Console.WriteLine("SizeOf(INFO2)=" & Marshal.SizeOf(x).ToString())
        Console.WriteLine("SizeOf(INFO3)=" & Marshal.SizeOf(y).ToString())
        Console.ReadLine()
    End Sub
End Module


さらん  2007-09-28 00:56:33  No: 99483

ありがとうございます!
教えていただいたコードにてテストすると、思った値が返ってきました。
で、ちょっと変更してやると…だめでした…。

Imports System.Runtime.InteropServices
Module Module1
    Structure INFO1
        Dim a As Integer
        Dim b As Byte
    End Structure

    Structure INFO2
        Dim a As Integer
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> Dim b() As INFO1
    End Structure

    Structure INFO3
        Dim a As Integer
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> Dim b() As Integer
    End Structure

    Sub Main()
        Dim x As INFO2, y As INFO3
        ReDim x.b(3), y.b(3)
        Console.WriteLine("SizeOf(INFO2)=" & Marshal.SizeOf(x).ToString())
        Console.WriteLine("SizeOf(INFO3)=" & Marshal.SizeOf(y).ToString())
        Console.ReadLine()
    End Sub
End Module

実際には24が返ってくるはずなのですが、実際には36が返ってきてしまいます。
どうやらINFO1が8バイトとなってしまっているようです。

どのように利用するかというと、
ハードディスクにあと何件データが保存できるか求めたいのです。
ハードディスクの空き容量は取得できたので、あとデータ構造のサイズがわかれば
単純計算で求まるかなと…。

よろしくお願いします…。


魔界の仮面弁士  2007-09-28 01:09:18  No: 99484

> 実際には24が返ってくるはずなのですが、実際には36が返ってきてしまいます。
返ってくる「はず」という表現はどうかと思いますが。(^^;
VB6 で試した場合も、Len=24、LenB=36 ですよね。

で、その件については、すでに最初の回答で述べているように、
>>> もし、そうしたメンバ間のパディングの扱いまで考慮する必要が
>>> あるのなら、StructLayoutAttribute 属性の併用を検討してみてください。
ということです。すなわち、
  <StructLayout(LayoutKind.Sequential, Pack:=1)> Structure INFO1
  <StructLayout(LayoutKind.Sequential, Pack:=1)> Structure INFO2
のように属性を付加するということです。

> ハードディスクにあと何件データが保存できるか求めたいのです。
それは、シリアライズの方法に依存するのでは無いでしょうか?

XML 形式で保存した場合、BinaryFormatter で永続化した場合、
独自形式で保存した場合、さらにそれらを圧縮した場合などなど…。


さらん  2007-09-28 01:17:15  No: 99485

できました!
長々と本当にありがとうございました!
本当に助かりました…。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加