Strukturen


Syntax
Structure <Name> [Extends <Name>] [Align <numerischer konstanter Ausdruck>]
  ...
EndStructure 
Beschreibung
Structure ist nützlich, um Benutzertypen zu definieren und um Zugriff auf einige Speicherbereiche des OS zu erhalten. Strukturen können für das schnellere und einfachere Verwalten von großen Datenbeständen benutzt werden. Sie sind sehr nützlich, um mit ihrer Hilfe in einem Objekt alle zusammengehörenden Informationen gruppieren zu können. Auf die Struktur-Felder wird mit dem \ Operator zugegriffen. Strukturen können auch verschachtelt werden. Statische Arrays werden innerhalb von Strukturen unterstützt.

Dynamische Objekte wie Arrays, Listen und Maps werden innerhalb von Strukturen unterstützt und werden automatisch initialisiert, wenn das Objekt mit Hilfe der Struktur erstellt wird. Um solche Felder zu deklarieren, verwenden Sie die folgende Schlüsselwörter: Array, List und Map.

Der optionale Extends Parameter ermöglicht eine Struktur mit neuen Feldern (aus einer bereits definierten Struktur) zu erweitern. Alle in der erweiterten (nach Extends angegebenen) Struktur gefundenen Felder werden in der neu definierten Struktur verfügbar sein und werden vor den neuen Feldern platziert. Dies ist nützlich, um einfache Vererbung von Strukturen durchzuführen.

Nur für fortgeschrittene Anwender: Der optionale Align Parameter ermöglicht es, die Ausrichtung (englisch "Alignment") zwischen jedem Struktur-Feld einzustellen. Die standardmäßige Ausrichtung (auch Anordnung) ist 1, was keine Ausrichtung bedeutet. Zum Beispiel, wenn die Ausrichtugn auf 4 eingestellt wird, dann wird jedes Feld-Offset auf einer 4-Byte-Grenze liegen. Dies kann helfen, eine bessere Leistung beim Zugriff auf die Felder der Struktur zu erreichen. Aber es kann auch mehr Speicher benötigen, da etwas Platz zwischen den einzelnen Feldern verschwendet wird. Der besondere Wert #PB_Structure_AlignC kann verwendet werden, um die Struktur wie in der Sprache C auszurichten, nützlich beim Importieren von C-Strukturen für die Verwendung mit API-Funktionen.

SizeOf kann bei Strukturen benutzt werden, um die Größe der Struktur zu ermitteln. OffsetOf kann verwendet werden, um den Index des angegebenen Felds zu ermitteln.

Bitte beachten Sie, dass sich in Strukturen ein statisches Array[] nicht so verhält wie das normale BASIC Array (definiert mittels Dim), um konform zum C/C++ Strukturen Format zu bleiben (was direkte API Strukturen Portierung ermöglicht). Dies bedeutet, dass a[2] ein Array von 0 bis 1 definiert, wogegen Dim a(2) ein Array von 0 bis 2 anlegt. Funktionen der Array-Bibliothek arbeiten ebenfalls nicht mit statischen Arrays.

Bei der Verwendung von Zeigern in Strukturen muss der '*' weggelassen werden, einmal mehr zur Erleichterung der API-Code Portierung. Dies kann als eine Kuriosität angesehen werden (und um ehrlich zu sein, ist sie das auch), aber es ist so seit dem Beginn von PureBasic und viele, viele Quellcode bauen darauf, weshalb es auch nicht geändert wird.

Bei der Verwendung vieler Strukturfelder können Sie den Umfang einzugebenden Codes vereinfachen und seine Lesbarkeit erhöhen, wenn Sie die With : EndWith Schlüsselwörter benutzen.

Es ist möglich, eine komplette Struktur zu kopieren, indem mittels des Gleichheitszeichens (=) eine Zuweisung zwischen zwei Struktur-Elementen des gleichen Typs vorgenommen wird.

ClearStructure kann verwendet werden, um einen strukturierten Speicherbereich zu löschen. Dies ist für die fortgeschrittene Anwendung gedacht, wenn Zeiger beteiligt sind.

Beispiel

  Structure Person
    Name.s
    ForName.s 
    Age.w 
  EndStructure
  
  Dim MyFriends.Person(100)
  
  ; Hier wird die Position '0' des Arrays MyFriend()
  ; eine Person und deren Informationen enthalten.
  
  MyFriends(0)\Name = "Andersson"
  MyFriends(0)\Forname = "Richard" 
  MyFriends(0)\Age = 32

Beispiel: Eine komplexere Struktur (verschachtelt und statisches Array)

  Structure Window
    *NextWindow.Window  ; verweist auf ein anderes Window Objekt
    x.w 
    y.w
    Name.s[10]  ; 10 Namen verfügbar (von 0 bis 9)
  EndStructure

Beispiel: Erweiterte ("extended") Struktur

  Structure MyPoint
    x.l 
    y.l
  EndStructure

  Structure MyColoredPoint Extends MyPoint
    color.l 
  EndStructure

  ColoredPoint.MyColoredPoint\x = 10
  ColoredPoint.MyColoredPoint\y = 20
  ColoredPoint.MyColoredPoint\color = RGB(255, 0, 0)

Beispiel: Kopieren von Strukturen

  Structure MyPoint
    x.l 
    y.l
  EndStructure

  LeftPoint.MyPoint\x = 10
  LeftPoint\y = 20
  
  RightPoint.MyPoint = LeftPoint
  
  Debug RightPoint\x
  Debug RightPoint\y

Beispiel: Dynamisches Objekt

  Structure Person
    Name$
    Age.l
    List Friends$()
  EndStructure

  John.Person
  John\Name$ = "John"
  John\Age   = 23
  
  ; Jetzt fügen wir einige Freunde zu John hinzu
  ;
  AddElement(John\Friends$())
  John\Friends$() = "Jim"

  AddElement(John\Friends$())
  John\Friends$() = "Monica"
  
  ForEach John\Friends$()
    Debug John\Friends$()
  Next

Beispiel: Statische, dynamische Arrays und Übergabe einer Struktur an eine Prozedur

  Structure Whatever
    a.l
    b.l[2]          ; Statisches Array (Standard C) mit 2 Werten b[0] und b[1], nicht in der Größe veränderbar
    Array c.l(3,3)  ; Dynamisches Array mit 16 Werten c(0,0) bis c(3,3), in der Größe veränderbar mittels ReDim()
  EndStructure

  MyVar.Whatever

  Procedure MyProcedure(*blahblah.Whatever)
    *blahblah\a = 5
    *blahblah\b[0] = 1
    *blahblah\b[1] = 2
    *blahblah\c(3,3) = 33
  EndProcedure

  MyProcedure(@MyVar)
  Debug MyVar\a
  Debug MyVar\b[0]
  Debug MyVar\b[1]
  Debug MyVar\c(3,3)
  
  ;Debug MyVar\c(0,10) ; 'Index außerhalb der erlaubten Grenzen' Fehler
  ReDim MyVar\c(3,10)  ; Beachte: nur die letzte Dimension kann in der Größe verändert werden!
  Debug  MyVar\c(0,10) ; Cool, das Array ist jetzt größer!

Beispiel: Verschachtelte Struktur(en)

  Structure pointF 
    x.f 
    y.f 
  EndStructure 
   
  Structure Field 
    Field1.q 
    Field2.s{6}
    Field3.s
    Array Tab.pointF(3)  
  EndStructure 
 
  Define MyVar.Field 
 
  MyVar\Tab(3)\x = 34.67

Syntax
StructureUnion
  Feld1.Typ
  Feld2.Typ
  ...
EndStructureUnion
Beschreibung
StructureUnion sind nur nützlich für fortgeschrittene Programmierer, welche etwas Speicher sparen wollen, indem sie einige Felder innerhalb derselben Struktur teilen. Sie funktionieren wie das 'Union' Schlüsselwort in C/C++.

Hinweis: Jedes Feld in der StructureUnion Deklaration kann einen unterschiedlichen Typ haben.

Beispiel

  Structure Type
    Name$
    StructureUnion
      Long.l      ; Jedes Feld (Long, Float und Byte) befindet sich
      Float.f     ; an derselben Adresse im Speicher.
      Byte.b      ;
    EndStructureUnion
  EndStructure

Beispiel: Erweitertes Beispiel (Datums-Verwaltung)

  Structure date
    day.s{2}
    pk1.s{1}
    month.s{2}
    pk2.s{1}
    year.s{4}
  EndStructure
  
  Structure date2
    StructureUnion
      s.s{10}
      d.date
    EndStructureUnion
  EndStructure
  
  Dim d1.date2(5)
  
  d1(0)\s = "05.04.2008"
  d1(1)\s = "07.05.2009"
  
  Debug d1(0)\d\day
  Debug d1(0)\d\month
  Debug d1(0)\d\year
  
  Debug d1(1)\d\day
  Debug d1(1)\d\month
  Debug d1(1)\d\year
    
  d2.date2\s = "15.11.2010"
  
  Debug d2\d\day
  Debug d2\d\month
  Debug d2\d\year

Beispiel: Ausrichtung (Alignment)

  Structure Type Align 4
    Byte.b
    Word.w
    Long.l
    Float.f
  EndStructure
  
  Debug OffsetOf(Type\Byte)   ; wird 0 ausgeben
  Debug OffsetOf(Type\Word)   ; wird 4 ausgeben
  Debug OffsetOf(Type\Long)   ; wird 8 ausgeben
  Debug OffsetOf(Type\Float)  ; wird 12 ausgeben

Beispiel: Zeiger (Pointer)

  Structure Person
    *Next.Person ; Hier ist der '*' zwingend, um einen Zeiger zu deklarieren
    Name$
    Age.b
  EndStructure

  Timo.Person\Name$ = "Timo"
  Timo\Age = 25
  
  Fred.Person\Name$ = "Fred"
  Fred\Age = 25
  
  Timo\Next = @Fred ; Bei der Verwendung eines Zeigers wird der '*' weggelassen
  
  Debug Timo\Next\Name$ ; Wird 'Fred' ausgeben