DIM

Aus C64-Wiki
Zur Navigation springenZur Suche springen
DIM
Syntax: DIM <Variable>[(<Index-Zahl>[,<Index-Zahl>...])][,<Variable>[(<Index-Zahl>[,<Index-Zahl>...])]...]
Parameter
<Variable>: Name der definierten Variable
<Index-Zahl>: Höchster Indexwert innerhalb der Dimension
Einordnung
Typ: Anweisung
Kontext: Variablen
Aufgabe: Deklaration von Variablen und Festlegen von (mehrdimensionalen) Feldern
Abkürzung: dI
Token: $86 (134)
Verwandte Befehle
CLR

Anmerkung: Dieser Artikel beschreibt den BASIC-Befehl DIM unter BASIC V2 des Commodore 64.


Der BASIC-Befehl DIM (von: Dimension) dient der Deklaration von Variablen und zum Festlegen von (mehrdimensionalen) Feldern (engl. Array) für den angegebenen Variablentyp (normale Zahl bzw. Gleitpunkt oder Fließkomma; String bzw. Zeichenkette $ ; Ganzzahl bzw. Integer %), um z. B. Tabellen, Matrizen, Vektoren und dergleichen abzubilden.

Beschreibung[Bearbeiten | Quelltext bearbeiten]

Die bei DIM nach dem Variablennamen in Klammern anzugebenden Werte legen die Anzahl der Dimensionen und den maximal nutzbaren Index des Felds pro Dimension fest. Der maximale Index kann in jeder Dimension 32767 nicht übersteigen. Die Anzahl der Dimensionen (Indizes) eines Feldes beschränkt sich theoretisch auf maximal 255. Die gesamte Größe des Feldes wird weiterhin durch den verfügbaren Speicher begrenzt.

Ein per DIM A(20) dimensioniertes entsprechend aus Fließkommazahlen bestehendes eindimensionales Feld besteht also aus 21 Elementen, mit A(0) als erstem und A(20) als letztem Element.

Mit der Dimensionierung wird nicht nur der nötige Speicher reserviert, sondern die Werte automatisch mit 0 (bei Fließkomma und Ganzzahl) bzw. mit einer leeren Zeichenkette (Länge 0) vorbelegt. Gängig ist beispielsweise die Verwendung von drei oder 4 Dimensionen für Anwendungen im Bereich der 3D-Berechnungen und räumlichen Modellierung.

Felder mit einer Indizierung unterhalb von 11 (für einen Indexbereich von 0 bis 10, bei mehrdimensionalen Feldern von allen Dimensionen zu erfüllen) können direkt ohne vorangegangenen BASIC-Befehl DIM genutzt werden. Der BASIC-Interpreter reserviert in dem Fall den Platz für ein entsprechend dimensioniertes Feld mit maximalem Index 10 in jeder Dimension automatisch.

Auch einfache Variablen können per DIM deklariert werden (Beispiel: DIM A%). Dadurch wird der BASIC-Interpreter angewiesen, Platz für die jeweilige Variable im Speicher zu reservieren. Der Variablenbereich ist als einfache Liste organisiert, die beim Zugriff auf eine Variable vom Interpreter sequenziell durchsucht werden muss. Entsprechend sollten häufig verwendete Variablen zuerst deklariert werden und sich damit am Anfang der Liste befinden. Dabei DIM zu benutzen ist eleganter als etwaige Pseudozuweisungen, die zudem mehr Programmplatz in Anspruch nehmen.

Die frühe Deklaration ist auch aus anderem Grunde vorteilhaft, da sonst undeklarierte Variablen den Variablenbereich bei der ersten Verwendung dynamisch erweitern und damit das zeitraubende Umkopieren des gesamten Array-Bereichs (wenn dieser sehr ausgedehnt ist) auslösen. Hier kann es dann zu merklichen, ungeplanten Verzögerungen im Programmablauf kommen.

Variablennamen können gleichzeitig für einfache Variablen und als Feld benutzt werden. Die Inhalte sind dann unabhängig (siehe Beispiel unten).

Der BASIC-Befehl DIM darf nur einmal pro Feld-Variable ausgeführt werden, ansonsten erscheint die BASIC-Fehlermeldung REDIM'D ARRAY ERROR.

Wird der Höchstwert von 32767 Index-Zahlen überschritten, so gibt es die BASIC-Fehlermeldung ?ILLEGAL QUANTITY ERROR und wenn der RAM-Speicher für die Dimensionierung nicht ausreicht, wird die BASIC-Fehlermeldung ?OUT OF MEMORY ERROR ausgegeben.

Der spätere Zugriff auf ein Feldelement außerhalb der Dimensionsgrenzen wird mit ?BAD SUBSCRIPT ERROR quittiert.

Speicherverbrauch[Bearbeiten | Quelltext bearbeiten]

Der Speicherverbrauch eines Arrays kann wie folgt berechnet werden:

Für den Vorspann (Header):

  • 2 Bytes für den Feldnamen (bei String-Variablen wird das 8. Bit des 2. Bytes gesetzt, bei Ganzzahlvariablen wird das 8. Bit von beiden Bytes gesetzt)
  • 2 Bytes für die Anzahl der Bytes des gesamten Eintrags (inklusive Vorspann)
  • 1 Byte für die Anzahl der Dimensionen
  • je 2 Bytes für die Größe einer Dimension (also Anzahl der Dimensionen mal zwei)

Für die Daten (Feldelemente):

  • 2 Bytes für jedes Element bei Ganzzahlvariablen (Integer)
  • 5 Bytes für jedes Element bei Gleitpunkt- bzw. Fließkommavariablen (normale, einfache Zahlenvariable)
  • 3 Bytes für jedes Element bei Zeichenkettenvariablen (String) - enthält den String-Descriptor: das 1. Byte ist die Länge des Strings, die anderen beiden geben einen Zeiger auf den Speicherbereich, der den eigentlichen String speichert; dieser befindet sich im String-Heap oder als Konstant-String im Programmcode.

Geschwindigkeit[Bearbeiten | Quelltext bearbeiten]

Das BASIC V2 des C64 benötigt ca. 4 Millisekunden für den Zugriff auf ein Element eines eindimensionalen Felds, sofern keine weiteren Berechnungen für den Index angestellt werden, erreicht also maximal rund 250 Zugriffe pro Sekunde. Bei einem zweidimensionalen Feld braucht jeder Zugriff ca. 6 Millisekunden, bei einem dreidimensionalen Feld ca. 8 Millisekunden, bei einem vierdimensionalen Feld ca. 10 Millisekunden.

In die Zugriffsgeschwindigkeit geht auch ein:

  • Position des Felds im Speicher - da das BASIC die Liste aller definierten Felder beim Zugriff linear durchsucht (wie normale Variablen auch), sind früh im Programmablauf angelegte Felder am schnellsten.
  • Art des Index-Parameters - früh im Programmablauf angelegte Variablen oder Konstante sind am schnellsten.

Der Grund für den langsameren Zugriff auf mehrdimensionale Felder liegt darin, dass die interne Berechnung der Speicherstelle, auf die schließlich zugegriffen werden muss, für mehrdimensionale Felder aufwändiger ist. Die dabei stattfindende Berechnung ist aber wesentlich effizienter (Ganzzahlmultiplikation), als etwa die rechnerische Abbildung mehrerer Dimensionen auf ein eindimensionales Array durch einen Ausdruck (wo sich neben dem aufwändigeren Parsing des BASIC-Codes auch noch die Ausdrucksauswertung durch Fließkommaoperationen zu Buche schlägt).

Um Platz zu sparen, kann es dennoch praktikabler sein, einen berechneten Index einzusetzen, falls das Feld nicht in allen Dimensionen gleichförmige Ausdehnungen hat.

Beispiele[Bearbeiten | Quelltext bearbeiten]

DIM Z(100) 

Die Gleitpunktvariable Z wird als Feld mit 101 Elementen dimensioniert (Index beginnt bei 0!).

DIM Z1$(12,31) 

Die Zeichenkettenvariable Z1$ wird auf eine Tabelle mit 13*32 Elementen dimensioniert;
Beispiel für Berechnungen in 2D: Jahreskalender mit Monat und Tag.

DIM Z%(22,15,11)

Die Ganzzahlvariable Z% wird auf eine Matrix mit 23*16*12 Elementen dimensioniert;
Beispiel für Berechnungen in 3D: Länge, Breite, Höhe.

Q=1000: DIM A(Q), B$(Q), C%(Q) 

Es können auch mehrere Variablen gleichzeitig deklariert werden.

Q(10,5)=10 

Hier wird automatisch ein 2-dimensionales Feld mit Q(0,0) bis Q(10,10) angelegt. Alle Elemente bis auf Q(10,5) haben nun den Wert 0.

A$="A":A$(0)="B":PRINT A$,A$(0)
A         B

Variablennamen können gleichzeitig als einfache Variable und als Feld benutzt werden. Die Variablen sind unabhängig.

DIM I,J,K

Die Variablen werden deklariert und so als erste im Variablenbereich angelegt. Damit greift der Interpreter schneller auf sie zu, wenn diese später, z.B. durch entsprechende Schleifen in Matrizenberechnungen, extensiv verwendet werden.

POKE 49,PEEK(47) : POKE 50,PEEK(48)

Setzt man den STREND-Zeiger auf den Wert von ARYTAB, werden alle Arrays gelöscht und man kann ein Array erneut dimensionieren.

10 DIM A%(40), B%(40)
20 POKE 9,PEEK(95+0*B%(0)):POKE 50,PEEK(96+0*B%(0)):POKE 49,PEEK(9)
30 DIM B%(40)

Man kann eine Anzahl der zuletzt definierten Arrays wieder freigeben, indem man STREND entsprechend umsetzt.[1] In Zeile 20 wird B%() wieder freigegeben, indem per 0*B%(0) ein Zugriff auf B%() ausgelöst (und das Ergebnis gleich wieder verworfen) und dann die Startadresse des Arrays aus 95/96 ausgelesen wird, wo sie der Interpreter durch $B21C hinterlassen hat. Das POKE9 wird nur als Zwischenspeicher benutzt. Zu beachten ist, dass BASIC-Code mit solchen Tricks nicht mehr mit Compilern kompatibel ist und dass sich nur die zuletzt definierten Felder freigeben lassen.

DIM A(7779):CLR

Beim C64 den BASIC-Speicher vollständig (bis auf 2 Bytes am Ende) mit 0 überschreiben (löschen). Kann etwa dazu verwendet werden, um den Hires-Bildschirmspeicher in der VIC-Bank 0 oder 1 (im Adressbereich $0000 bis $7FFF) zu löschen.

CLR:A%(0,0,0,0)=1:PRINT FRE(0)

legt 11×11×11×11 Elemente zu je 2 Bytes (Integer) "implizit" an (in Summe 29282 Bytes an Daten) und die Ausgabe zeigt einen verbleibenden Speicher (ohne Programm) von

 9614

Bytes.
Die Angabe weiterer Dimensionen führt zur Fehlerausgabe ?OUT OF MEMORY ERROR.


Weblinks[Bearbeiten | Quelltext bearbeiten]

WP-W11.png Wikipedia: Dynamischer Speicher (Heap)


Quellen[Bearbeiten | Quelltext bearbeiten]