Im Rahmen eines Computerprogramms müssen Daten im Arbeitsspeicher des digitalen Rechnersystems gespeichert werden.
Manche dieser Daten dürfen sich nicht ändern und sollen, solange das Computerprogramm abläuft konstante Werte haben; entsprechend spricht man von Konstanten!
Die allermeisten Daten dürfen und sollen sich aber ändern können; entsprechend spricht man von Variablen.
Für beide Arten von Daten gilt aber, dass jede zu speichernde Information -egal, ob konstant oder variabel- in einer bestimmten Form im Arbeitsspeicher abgelegt werden muss. Der Arbeitsspeicher eines digitalen Rechnersystems ist zumeist byte-orientiert. Das bedeutet, dass die Zentrale Verarbeitungseinheit (die Central Processing Unit) immer nur eine Gruppe von acht Bit, die man Byte nennt, verarbeiten kann (dies gilt nicht für die häufig in Geräten verwendeten sogenannten Mikrocontroller, die auch für eine bitweise Verarbeitung von Daten konstruiert sind).
Man kann sich den Arbeitsspeicher eines digitalen Rechnersystems wie einen sehr großen Schrank mit sehr sehr vielen Schubladen vorstellen, bei dem jede Schublade eine Nummer hat, die Adresse einer Speicherstelle. Jede dieser vielen Schubladen kann einen Bytewert, und das ist letztendlich ein Zahlenwert im Wertebereich von 0 bis 255, aufnehmen!
Im Bild nebenan ist beispielhaft ein Arbeitsspeicher der Größe 1 KByte (=1024 Byte) dargestellt. Die unterste „Schublade“ hat die Adresse 0 und die oberste „Schublade“ hat die Adresse 1023. Insgesamt hat der Arbeitsspeicher also 1024 „Schubladen“. Jede dieser „Schubladen“ kann ein einzelnes Byte aufnehmen. Ein Byte ist lediglich eine Gruppe (oder Tupel) von 8 Bit (Binary Digit = Binäre Ziffer).
Für die Speicherung der Daten werden dann in vielen Fällen mehrere dieser „Schubladen“ zu einer Einheit quasi zusammen gefasst.
Jede zu speichernde Information muss also in Form von Bits im Arbeitsspeicher abgelegt werden. Grundlegend gibt es verschiedene Informationsarten, die digitale Rechnersysteme verarbeiten können, die aber alle auf solche Binärmuster abgebildet werden müssen!
Diese sind:
- Numerische Daten (Zahlen)
- Alphanumerische Daten (Zeichen)
Bei den numerischen Daten unterscheidet man zwischen den Ganzzahlen und den Dezimalzahlen. Ganzzahlen können, wie schon die Bezeichnung nahe legt, lediglich ganze Zahlenwerte wie 0, 1, 1023, -42 etc. annehmen, aber eben keine Dezimalstellen haben. Dezimalzahlen können auch Dezimalstellen haben wie z.B. 1,38, 47,11 oder -3,527.
Alphanumerischen Daten sind entweder einzelne Zeichen, wie z.B. der Großbuchstabe A oder der Kleinbuchstabe z oder ein Satzzeichen wie das Ausrufezeichen !. Werden mehrere Zeichen als eine Zeichenfolge verstanden, spricht man von einer Zeichenkette bzw. von einem String. Wörter wie Hallo oder Welt bestehen aus einzelnen Zeichen, die aber zusammengesetzt das Wort bilden: Somit sind dies Zeichenketten!
Für alle diese verschiedenen Arten von Informationen werden in den digitalen Rechnersystemen verschiedene Formen der Speicherung verwendet. Die Form der Speicherung wird durch den sogenannten Datentyp festgelegt. Für jeden Datentyp gibt es einen Wertebereich (Domäne). Der einfachste Datentyp, den eine CPU verarbeiten kann, ist hierbei der Datentyp Integer, der die Speicherung von Ganzzahlwerten ermöglicht.
Numerische Daten
Ganzzahlen
Ein Integer ist ein Ganzzahlwert, dessen Größe sich aus der verwendeten Anzahl von Bits zur Speicherung dieses Wertes ergibt. Da dies quasi die „natürliche“ Weise einer Information in digitalen Rechnersystemen ist, lässt sich ein Integer-Wert sehr einfach und sehr schnell verarbeiten.
Die Anzahl Bits, die für einen Integer-Wert verwendet wird, richtet sich fast immer nach der Anzahl der Datenbits, die eine CPU (oder ein Mikrocontroller) mit ihrem Datenbus „in einem Rutsch“ verarbeiten kann. Die erste Intel-CPU, der i4004, war z.B. eine 4 Bit CPU. Die Intel CPU i8008 hatten einen Datenbus mit der Breite 8 Bit und gilt als die erste 8 Bit CPU. Eine 16 Bit- oder 32 Bit-CPU hingegen hat damit typischerweise einen 16 Bit- oder 32 Bit-Datenbus und kann somit „in einem Rutsch“ 16 oder 32 Bit über den Datenbus übertragen.
Die verwendete Anzahl von Bits bestimmt somit den Wertebereich für die Ganzzahlen. Hierbei muss man noch zwischen den vorzeichenlosen und den vorzeichenbehafteten Ganzzahlen unterscheiden.
Bei vorzeichenlosen Ganzzahlen ist der kleinste Zahlenwert die Null und der größte Zahlenwert ist 2 hoch N – 1, wobei N die Anzahl der Bits darstellt. Für Ganzzahlen, die mittels 8 Bit gespeichert werden, lautet der Wertebereich: 0 bis 2 hoch 8 – 1 = 256 – 1 = 255.
Bei den vorzeichenbehafteten Ganzzahlen wir dieser Wertebereich quasi halbiert und die eine Hälfte stellt die positiven Ganzzahlen dar und die zweite Hälfte wird für die negativen Ganzzahlen verwendet, wobei die Null zu den positiven Ganzzahlen gerechnet wird.
Die folgende Tabelle zeigt die Wertebereiche für 4, 8, 16 und 32 Bit-Ganzzahlen (vorzeichenlos und vorzeichenbehaftet):
Anzahl Bit | ohne VZ Min | ohne VZ Max | mit VZ Min | mit VZ Max |
---|---|---|---|---|
4 | 0 | 15 | -8 | +7 |
8 | 0 | 255 | -128 | +127 |
16 | 0 | 65535 | -32768 | +32767 |
32 | 0 | 4.294.967.295 | -2.147.483.648 | +2.147.483.647 |
Der 4 Bit Integer spielt heute sicherlich keine Rolle mehr. Für die Speicherung eines 8 Bit Integers wird im Arbeitsspeicher ein Byte benötigt, für einen 16 Bit Integer werden zwei aufeinanderfolgende Byte verwendet und für einen 32 Bit Integer sind es somit vier Byte. Ein 64 Bit Integer benötigt acht aufeinander folgende Byte.
Bei den Integer-Werten mit 16, 32 oder gar 64 Bit ist noch etwas wichtig! Und zwar die sogenannte Byteorder (Reihenfolge der Bytes im Arbeitsspeicher). Bei einem 32 Bit Integer werden ja vier Byte benötigt, die z.B. an den Adressen 4, 5, 6 und 7 gespeichert sind:
Dieser 32 Bit-Wert könnte jetzt auf die beiden folgenden zwei Arten dargestellt werden:
Wenn man also einen 32 Bit-Wert hat, kann dieser also entweder beginnend mit den höchstwertigen Byte oder beginend mit niederwertigsten Byte im Arbeitsspeicher abgelegt werden. Diese Byte-Order ist eine konstruktive Eigenschaft der CPU. Sieht man sich den Arbeitsspeicher eines digitalen Rechnersystems mit einem Hex-Editor an, muss man wissen, welche Byte-Order die jeweilige CPU verwendet und diese Reihenfolge entsprechend berücksichtigen. Auch bei der Datenübertragung zwischen verschiedenen Systemwelten muss eine entsprechende Anpassung vorgenommen werden.
Alle Intel CPUs legen solche 16, 32 oder 64 Bit-Werte beginnend mit dem niederwertigsten Byte im Arbeitsspeicher ab (Little Endian).
In der Programmierung wird der Datentyp Integer sehr häufig verwendet, da er wie bereits erwähnt der quasi „natürlichen“ Darstellung von Zahlen in einem digitalen Rechnersystem entspricht.
Dezimalzahlen
Zahlenwerte, die Dezimalstellen aufweisen sollen, werden in einem komplexen genormten Format gespeichert. Die Norm IEEE 754 beschreibt dieses Format.
Bei den sogenannten Gleitkomma– oder Fließkommazahlen werden diese Zahlen in ein definiertes Format überführt, bei dem das Komma quasi an eine bestimmte Position gleitet bzw. fließt. Jede Dezimalzahl wird als Zahl mit einer 10er Potenz geschrieben.
Ich möchte das an zwei sehr einfach gehaltenen Beispielen für die Zahlen -123,456789 und 0,000123456789 im Dezimalsystem verdeutlichen:
Für die Zahl -123,456789 gleitet das Komma soweit, dass vor dem Komma nur noch eine Stelle steht und die Verschiebungen als Zehnerexponent gespeichert werden: -1,23456789 * 10 ^ +2.
Für die Zahl 0,000123456789 gleitet das Komma ebenfalls soweit, dass auch hier nur noch eine Stelle vor dem Komma steht und die Verschiebungen als Zehnerexponent notiert werden: 0,123456789 * 10 ^ -3
Gespeichert (stark vereinfacht!) werden nun zwei Werte: Die Zahl vor dem Zehnerexponent inklusive Vorzeichen (diese nennt man Mantisse) und der Zehnerexponent (mit Vorzeichen).
Bei digitalen Rechnersystemen werden diese Zahlenwerte jedoch nicht im 10er System sondern im 2er System (Binärsystem) gespeichert.
Für die Speicherung dieser Dezimalzahlen wird (je nach Datentyp) eine festgelegte Anzahl von Bits verwendet. So stehen z.B. für den Datentyp float lediglich 4 Byte (=32 Bit) zur Verfügung. Diese werden jetzt aufgeteilt auf das Vorzeichen der Mantisse ( 1 Bit), die Mantisse (23 Bit) und den Exponenten (8 Bit).
Durch diese Begrenzungen sind der Wertebereich und die Genauigkeit solcher Dezimalzahlen eingeschränkt!
Eine Variante zu den Gleitkommazahlen sind die Festkommazahlen. Diese werden anders gespeichert, wodurch eine garantierte Genauigkeit für eine bestimmte Anzahl von Dezimalstellen gewährleistet wird.
Alphanumerische Daten
Zeichen
Ein Zeichen wird gespeichert, in dem man einem Zeichen eine festgelegte Bitkombination zuordnet. Diese Zuordnung erfolgt anhand von einer sogenannten Zeichensatztabelle. Eine sehr grundlegende Zeichencodierung (Zuordnung eines Zahlenwertes für ein bestimmtes Zeichen) ist die sogenannte ASCII-Tabelle. Deren Zuordnungen finden sich auch in den heute sehr verbreiteten Zeichencodierungen UTF-8 bzw. UTF-16 mittels Unicode.
Für die Speicherung eines einzelnen Zeichens werden je nach Codierung eine bestimmte Menge an Bits benötigt. Bei ASCII sind dies z.B. 7 Bit, wobei aufgrund der Tatsache, dass digitale Rechnersysteme zumeist 8 Bit (= ein Byte) große Speicherstellen verwenden, das höchstwertige Bit immer den Wert 0 hat. Bei UTF-8 werden eben 8 Bit pro Zeichen verwendet und bei UTF-16 werden zwei Byte für ein einzelnes Zeichen benötigt.
Ein einzelnes Zeichen lässt sich daher immer auch als Zahlenwert interpretieren!
Zeichenfolge (String)
Bei Zeichenfolgen werden die einzelnen Zeichen als Zahlenwerte der verwendeten Codierung aufeinanderfolgend im Speicher abgelegt. Um zu erkennen, wo eine Zeichenfolge beginnt bzw. endet wird häufig noch die Länge dieser Zeichenkette mitgespeichert. Oder es wird eine definierte Bitkombination am Ende einer Zeichenkette gespeichert, welche dann nicht zur Zeichendarstellung benutzt werden kann.
Datentypen in C#
In der Programmiersprache C# stehen zahlreiche sogenannte „integrierte Datentypen“ zur Verfügung. Die C#-Referenz gibt Aufschluss über die Wertebereiche und die jeweils benötigte Datenmenge eines jeden integrierten Datentyps.
Allerdings muss man noch folgende Unterscheidung beachten: Es gibt zwei Arten von Datentypen:
Bei den Werttypen wird direkt der Wert gespeichert. Hierzu zählen fast alle der oben genannten integrierten Datentypen mit Ausnahme der Zeichenkette! Die Zeichenkette (Datentyp string) ist ein Verweistyp.
Das bedeutet, dass nicht direkt der Wert gespeichert wird, sondern es wird eine Speicheradresse gespeichert, die angibt wo sich der tatsächliche Wert (bei einem String die Abfolge der einzelnen Zeichen und als Verwaltungsinformation die Anzahl der Zeichen) befindet, eben ein Verweis!. Diese indirekte Art der Speicherung findet sich immer dann, wenn für einen Wert die benötigte Speichermenge variiert.
Dies macht es auch möglich, dass mehrfach auf diesen tatsächlichen Wert verwiesen werden kann!
Dies hat auch Konsequenzen bei der Verwendung von solchen Speicherstellen im Rahmen von Prozeduren/Funktionen/Methoden!
Speicherung von numerischen Daten
Für numerische Werte stehen die „integralen numerischen Typen“ und die „numerischen Gleitkommatypen“ zur Verfügung.
Erstere erlauben die Speicherung von Ganzzahlwerten innerhalb bestimmter Wertebereiche, die sich aufgrund der Anzahl zur Verfügung stehender Bits ergeben.
Letztere ermöglichen die Speicherung von Dezimalzahlen mit einer gewissen Genauigkeit hinsichtlich der Anzahl von Dezimalstellen und hinsichtlich der Größe des Exponenten.
Weiter zu Variable und Konstante
Nach oben zu Strukturierte Programmierung