Länge von Strukturen.

17/02/2011 - 17:18 von Wolfgang Badura | Report spam
Hallo Spezialisten!

Ich grüble bereits einen ganzen Nachmittag über einem Problem.

Anbei der Code:

Public Class Form1
' ****** Strukturen für die Iconfile-Datei ******
<StructLayout(LayoutKind.Sequential)> _
Private Structure IconHeader
Dim ihReserved As UInt16
Dim ihType As UInt16
Dim ihCount As UInt16
End Structure

<StructLayout(LayoutKind.Sequential)> _
Private Structure IconEntry
Dim ieWidth As Byte ' Breite in Pixeln
Dim ieHeight As Byte ' Höhe in Pixeln
Dim ieColorCount As Byte ' Anzahl der Farben (bei 256 Farben -->
0)
Dim ieReserved As Byte ' =0
Dim iePlanes As UInt16 ' Anzahl der Farbplanes =1, bei 16
Farben=0
Dim ieBitCount As UInt16 ' Bits pro Pixel (32 bei 256 Farben, 0
bei 16 Farben)
Dim ieBytesInRes As UInt32
' = Lànge BitMapHeader (@)
' + (bei 256 Farben Anzahl Pixel * 4,
bei 16 Farben Anzahl Pixel\2)(XOR)
' + 128 Bytes TransparenzInfos (ANF)
Dim ieImageOffset As UInt32 ' Lànge IconHeader (=6) + Lànge
IconEntry () = 22
End Structure

' ****** Struktur myStruct ******
<StructLayout(LayoutKind.Sequential)> _
Private Structure myStruct
Dim Data1 As UInt32
Dim Data2 As UInt16
Dim Data3 As UInt16
Dim data4 As UInt16
End Structure

Public Structure Guid
Dim data1 As Integer
Dim data2 As Short
Dim data3 As Short
<VBFixedArray(7)> Dim data4() As Byte
' aus http://vbcity.com/forums/t/133014.aspx
' upgrade_todo: "initialize" must be called to initialize instances of
this
' structure. click for more:
'ms-help://ms.vscc.v80/dv_commoner/loca...f27b"'
Public Sub initialize()
ReDim data4(7)
End Sub
End Structure

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim IconHeader As New IconHeader
Dim IconEntry As New IconEntry
Dim myStruct As New myStruct
Dim Guid As New Guid

Trace.WriteLine("Marshal.SizeOf(IconHeader): " &
Marshal.SizeOf(IconHeader))
Trace.WriteLine("Marshal.SizeOf(IconEntry): " &
Marshal.SizeOf(IconEntry))
Trace.WriteLine("Marshal.SizeOf(myStruct): " &
Marshal.SizeOf(myStruct))
Trace.WriteLine("Marshal.SizeOf(Guid): " & Marshal.SizeOf(Guid))
End Sub
End Class

Ergebnis:
Marshal.SizeOf(IconHeader): 6
Marshal.SizeOf(IconEntry): 16
Marshal.SizeOf(myStruct): 12
Marshal.SizeOf(Guid): 12

Ich verstehe das alles nicht wirklich.
Hat jemand dafür eine Erklàrung?

Warum ist myStruct 12 Bytes lang?
Warum ist Guid nicht 15 Bytes lang?
Die Làngen der restlichen Strukturen stimmen.

Kann ich die Lànge 10 für myStruct irgendwie erzwingen?
Gibt es da ev. einen Bug?

Danke an alle,
Wolfgang
 

Lesen sie die antworten

#1 Armin Zingler
17/02/2011 - 19:42 | Warnen spam
Am 17.02.2011 17:18, schrieb Wolfgang Badura:
Hallo Spezialisten!

Ich grüble bereits einen ganzen Nachmittag über einem Problem.

Anbei der Code:

Public Class Form1
' ****** Strukturen für die Iconfile-Datei ******
<StructLayout(LayoutKind.Sequential)> _
Private Structure IconHeader
Dim ihReserved As UInt16
Dim ihType As UInt16
Dim ihCount As UInt16
End Structure

<StructLayout(LayoutKind.Sequential)> _
Private Structure IconEntry
Dim ieWidth As Byte ' Breite in Pixeln
Dim ieHeight As Byte ' Höhe in Pixeln
Dim ieColorCount As Byte ' Anzahl der Farben (bei 256 Farben -->
0)
Dim ieReserved As Byte ' =0
Dim iePlanes As UInt16 ' Anzahl der Farbplanes =1, bei 16
Farben=0
Dim ieBitCount As UInt16 ' Bits pro Pixel (32 bei 256 Farben, 0
bei 16 Farben)
Dim ieBytesInRes As UInt32
' = Lànge BitMapHeader (@)
' + (bei 256 Farben Anzahl Pixel * 4,
bei 16 Farben Anzahl Pixel\2)(XOR)
' + 128 Bytes TransparenzInfos (ANF)
Dim ieImageOffset As UInt32 ' Lànge IconHeader (=6) + Lànge
IconEntry () = 22
End Structure

' ****** Struktur myStruct ******
<StructLayout(LayoutKind.Sequential)> _
Private Structure myStruct
Dim Data1 As UInt32
Dim Data2 As UInt16
Dim Data3 As UInt16
Dim data4 As UInt16
End Structure

Public Structure Guid
Dim data1 As Integer
Dim data2 As Short
Dim data3 As Short
<VBFixedArray(7)> Dim data4() As Byte



VBFixedArray hat keine Auswirkung auf den Marshaller
sondern nur auf die VB-eigenen Dateioperationen
wie FilePut/FileGet.

Verwende stattdessen MarshalAs(ByValArray) mit sizeconst := 8

' aus http://vbcity.com/forums/t/133014.aspx
' upgrade_todo: "initialize" must be called to initialize instances of
this
' structure. click for more:
'ms-help://ms.vscc.v80/dv_commoner/loca...f27b"'
Public Sub initialize()
ReDim data4(7)
End Sub
End Structure

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim IconHeader As New IconHeader
Dim IconEntry As New IconEntry
Dim myStruct As New myStruct
Dim Guid As New Guid

Trace.WriteLine("Marshal.SizeOf(IconHeader): " &
Marshal.SizeOf(IconHeader))
Trace.WriteLine("Marshal.SizeOf(IconEntry): " &
Marshal.SizeOf(IconEntry))
Trace.WriteLine("Marshal.SizeOf(myStruct): " &
Marshal.SizeOf(myStruct))
Trace.WriteLine("Marshal.SizeOf(Guid): " & Marshal.SizeOf(Guid))
End Sub
End Class

Ergebnis:
Marshal.SizeOf(IconHeader): 6
Marshal.SizeOf(IconEntry): 16
Marshal.SizeOf(myStruct): 12
Marshal.SizeOf(Guid): 12

Ich verstehe das alles nicht wirklich.
Hat jemand dafür eine Erklàrung?

Warum ist myStruct 12 Bytes lang?



Ich musste auch erst lange suchen, obwohl ich meinte,
es verstanden zu haben:
Man muss immer zwei hintereinanderliegende Objekte im RAM betrachten:

- Bei "IconHeader" sind es alles Uint16. Somit kann das
nàchste Objekt vom selben Typ direkt hintendran
abgelegt werden. => Lànge=6

- Bei "myStruct" würde als nàchstes wieder ein Uint32
folgen. Somit muss auf 4-Byte-Grenze aufgerundet werden => Lànge

Dadurch ist gewàhrleistet, dass die Felder immer an
Vielfachen der Größe des Typs abgelegt sind.


Warum ist Guid nicht 15 Bytes lang?



s.o.

Selbst wenn VBFixedArray eine Auswirkung hàtte, bedeutet
die 7 die obere Grenze, also 0-7 sind 8 Elemente, somit Lànge.

Die Làngen der restlichen Strukturen stimmen.

Kann ich die Lànge 10 für myStruct irgendwie erzwingen?
Gibt es da ev. einen Bug?



Mit
<StructLayout(LayoutKind.Sequential, pack:=1)> _

Wie aber schon in der Hilfe steht: Wenn das nicht unbedingt sein
muss, sollte man die Standardausrichtung belassen weil sonst
die Performance darunter leiden könnte. In deinem Fall beginnt
Data1 dann nicht mehr immer an einer 4-Byte-Grenze wenn
die Lànge 10 ist.


Armin

Ähnliche fragen