C++ Kurs

Variablen

Die Themen:

Variablendefinition
Ganzzahl-Datentypen
Gleitkomma-Datentypen
Zeichen-Datentypen
Weitere Datentypen
Sonstiges zur Variablendefinition
Eigenschaften von Datentypen
sizeof() Operator

Variablendefinition

In dieser Lektion werden wir uns ansehen, wie Daten innerhalb eines Programms abgelegt werden.

Veränderbare Daten werden in so genannten Variablen abgelegt. Sie können einer Variable beliebig oft Werte zuweisen (siehe dazu später Lektion Zuweisungen), der alte Wert wird dann einfach überschrieben.

Bevor ein Wert in einer Variable abgelegt werden kann, muss die Variable vorher definiert werden. C++ unterstützt keine automatischen Variablendefinition wie z.B. BASIC. Eine Variablendefinition hat folgenden vereinfachten allgemeinen Aufbau:

<Datentyp> <Variablenname>;

An erster Stelle steht der Datentyp der Variable und danach folgt der Name (Bezeichner) der Variable. Da eine Variablendefinition auch eine ausführbare Anweisung ist, muss sie mit einem Semikolon abgeschlossen werden.

Der Datentyp bestimmt den Wertebereich der Variable und damit auch indirekt den Speicherplatz (Anzahl Bytes) den eine Variable belegt. Je mehr Speicher die Variable belegt, um so größer kann der in ihr abzulegende Wert prinzipiell sein. Mehr zu den Wertebereichen gleich noch.

Nach dem Datentyp folgt der Name der Variable. Über diesen Namen können Sie dann der Variable Werte zuweisen oder auch den aktuellen Wert auslesen. Dieser Name muss eindeutig sein, d.h. es darf keine zweite Variable (oder Funktion und ähnliches) mit gleichem Namen geben.

Obwohl die Schreibweise von Variablennamen beliebig ist, sollten Sie sich eine einheitliche Schreibweise angewöhnen. Im Kurs beginnen Variablennamen immer mit einem Kleinbuchstaben und bei Bedarf werden an den Wortgrenzen Großbuchstaben verwendet (z.B. maxTemp oder numberOfTiles).

Und noch ein Hinweis: versuchen Sie zu vermeiden, dass Namen einmal in englisch und das andere mal in deutsch vergeben. Denglisch sieht irgend wie unsauber aus.


Beachten Sie bitte, dass C++ streng zwischen Groß- und Kleinschreibung unterscheidet. So ist die Variable max nicht identisch mit der Variable Max. Allerdings sollten vermeiden, dass sich zwei unterschiedliche Variablen nur durch die Groß-/Kleinschreibung unterscheiden, alleine der guten Lesbarkeit wegen.



// Variable ausserhalb von main() definieren
int numberOfRanges;

// main() Funktion
int main()
{
   // Variable innerhalb von main() definieren
   int sinusValue;
   ...
   // weitere Variable definieren
   double result;
   ...
}

Für den Augenblick spielt es noch keine Rolle, ob Sie die Definition einer Variable vor main() vornehmen oder aber innerhalb von main(). Worin sich diese beiden Definition letztendlich unterscheidet, werden wir uns später noch genauer ansehen. Variablen können an beliebiger Stelle im Programm definieren werden, was den Vorteil hat, dass eine Variable genau an der Stelle definiert werden kann, an der sie zum ersten Mal auch benötigen wird.

Ganzzahl-Datentypen

C++ kennt folgende Ganzzahl-Datentypen, die auch als Integer-Datentypen bezeichnet werden:

signed char short int int long int
unsigned char unsigned short int unsigned int unsigned long int

Variablen der Datentypen signed char, short int, int und long int können sowohl positive wie auch negative Werte annehmen, während Variablen der Datentypen unsigned xxx nur positive Werte (einschließlich der 0) annehmen können.

Bei den Datentypen short und long kann die Angabe von int auch entfallen, d.h. anstelle short int kann zum Beispiel auch nur short geschrieben. Wenn Sie wollen, können Sie bei den Datentypen short int, int und long int noch explizit das Schlüsselwort signed voranstellen, also zum Beispiel signed short int, aber das ist nun wirklich die Langfassung. In der Praxis haben sich die Schreibweisen short, long, unsigned short und unsigned long eingebürgert. Software-Entwickler schreiben nun einmal nicht gerne mehr als unbedingt notwendig ist.

Bei den char-Datentypen ist signed bzw. unsigned zwingend vorgeschrieben. Es gibt auch noch den Datentyp char, der in einer späteren Lektion behandelt wird. Dieser char Datentyp ist aber nicht identisch mit dem signed char Datentyp.

Der Unterschied zwischen den Datentypen liegt im Wertebereich den eine Variable annehmen kann und damit indirekt auch im Speicherbedarf. Die Sprache C++ schreibt den Wertebereich der Datentypen nicht explizit vor, es muss jedoch immer folgender Zusammenhang gelten:

char   = 1 Byte
signed char  <=  short
short  <= int
int  <= long

1 Byte ist definiert als die Speichergröße, die benötigt wird, um ein Zeichen abzulegen. Dies sind in der Regel 8 Bit. Es mag aber durchaus einmal Implementierungen geben, bei denen 1 Byte aus 4 Bit oder gar 16 Bit besteht. Der C++ Standard sagt darüber nichts aus. Jedoch ist dem Autor zur Zeit kein gängiger Compiler bekannt, bei dem 1 Byte nicht 8 Bit groß ist.

Damit können Sie nun Integer-Variablen wie folgt definieren.


// short Variable definieren
short myValue;
// Variable mit großem Wertebereich definieren
signed long counter;
// Variable mit kleinem Wertebereich zur Aufnahme von nur positiven Zahlen
unsigned char index;

Welchen Wertebereich die einzelnen Datentypen aufnehmen können, hängt letztendlich vom verwendeten Compiler und der verwendeten Rechner-Plattform ab. In der nachfolgenden Tabelle sind die jeweiligen Wertebereiche wiedergegeben, wie Sie beim Einsatz des Visual C++ 2008 Express Edition vorkommen.

Datentyp    Wertebereich
signed char    -128...127
short    -32768... 32767
long    -2147483648...2147483647
unsigned char    0...255
unsigned short    0...65535
unsigned long    0...4294967295

Mehr zu den auf Ihrem System gültigen Wertebereichen und sonstigen Eigenschaften der verschiedenen Datentypen können Sie sich gleich noch ansehen.

Wenn Sie wollen, können Sie sich durch anklicken des Symbols links auch einmal ansehen, wie negative Zahlen im 2er Komplement dargestellt werden.

Gleitkomma-Datentypen

Für die Darstellung von Gleitkommazahlen stehen 3 verschiedene Datentypen zur Verfügung: float, double und long double. Der 'kleinste' Gleitkomma-Datentyp ist der Datentyp float, gefolgt vom Datentyp double und long double.

Diese Datentypen unterscheiden sich zum einen im darstellbaren Wertebereich und zum anderen, was fast noch wichtiger für Berechnungen ist, durch die Anzahl der Stellen, mit denen der Datentyp arbeitet.

Beim VC++ ist die Rechengenauigkeit der Datentypen double und long double identisch. Dies ist aber eine VC++ Besonderheit und kann bei anderen Compilern durchaus abweichen.

Damit Sie eine Vorstellung bekommen, wie sich der Datentyp auf die Berechnung auswirkt, nachfolgend zwei Beispiele.

Berechnung    float-Ergebnis    double-Ergebnis
1.0/3.0    0.3333333    0.3333333333333333
10.0/3.0    3.333333    3.333333333333333

Zeichen-Datentypen

Zum Abspeichern von Zeichen werden die Datentypen char und wchar_t verwendet. Der Datentyp char dient zur Aufnahme eines Zeichens das 1 Byte belegt, während der Datentyp wchar_t ein Zeichen eines erweiterten Zeichensatzes aufnehmen kann. In der Regel werden in wchar_t Zeichen abgelegt die nicht in einem Byte Platz finden. Denken Sie hierbei z.B. an den chinesischen Zeichensatz.


// char Variable definieren
char anyCharacter;
// Variable für den erweiterten Zeichensatz definieren
wchar_t unicodeChar;

Der Datentyp char ist ein eigenständiger Datentyp und entspricht nicht dem Datentyp signed char! Dieser Sachverhalt spielt später beim Überladen von Funktionen/Memberfunktionen noch wichtige Rolle.

Weitere Datentypen

Und gleich haben wir die Datentypen (wenigstens vorläufig) geschafft. Was uns jetzt noch fehlt, sind die Datentypen bool und void.

Der Datentyp bool kann nur die beiden Zustände (Werte) true und false annehmen. Er wird immer dann eingesetzt, wenn im Programm eine Aussage auf wahr (erfüllt) oder nicht wahr (nicht erfüllt) verglichen werden soll.


// Eine bool Variable definieren
bool allDone;

Der Datentyp void ist ein unvollständiger Datentyp, der niemals alleine auftreten kann. Er wird hauptsächlich als Returntyp von Funktionen/Memberfunktionen oder im Zusammenspiel mit Zeigern verwendet. Auf ihn werden wir später noch zurückkommen.

Es sei an dieser Stelle noch darauf hingewiesen, dass es noch weitere Datentypen gibt, die erst später im Kurs behandelt werden. Dies sind im Einzelnen:

Sonstiges zur Variablendefinition

Variablen lassen sich bei ihrer Definition auch gleich mit einem bestimmten Wert initialisieren (vorbelegen). Dies erfolgt in der Art, dass nach der Definition der Variable der Zuweisungsoperator = folgt und danach der Initialwert.


// int-Variable initialisieren
int startValue = 10;
// double-Variable initialisieren
double oneThird = 1.0/3.0;
// bool-Variable initialisieren
bool isDone = false;

Eine bei ihrer Definition initialisierte Variable können im Verlaufe des Programms jederzeit weitere Werte zugewiesen werden. Und selbstverständlich muss der Datentyp des Initialwerts auch mit dem Datentyp der Variable übereinstimmen. Mehr zum Datentyp des Initialwerts gleich bei der Behandlung von Konstanten.

Außerdem können Sie, um sich Schreibarbeit zu sparen, mehrere Variablen des gleichen Datentyps innerhalb einer Anweisung definieren. Die Namen der zu definierenden Variablen werden durch Komma voneinander getrennt. Zusätzlich können die Variablen bei Bedarf auch noch initialisiert werden.


// zwei int Variablen definieren
int startValue, endValue;
// zwei double-Variable definieren und initialisieren
double beginOfRange = -2.5, endOfRange = 2.5;

Eigenschaften von Datentypen

Wenn Sie das Symbol links anklicken können Sie sich ein kleines Programm ansehen, das einige Eigenschaften für die vorgestellten Datentypen ermittelt. Für die Ermittlung der Eigenschaften brauchen Sie das Programm (noch) nicht zu vollständig verstehen, da es hier schon ziemlich 'ins Eingemachte' geht (Stichwort: Templates). Geben Sie beim Aufruf der Funktion PrintNumLimits<DTYP>() innerhalb den spitzen Klammern lediglich den Datentyp an, dessen Eigenschaften Sie ermitteln wollen, übersetzen das Programm neu und starten es dann.

Aufruf Datentyp Eigenschaften
PrintNumLimits<unsigned long>(); Minimum: 0
Maximum: 4294967295
Anzahl Bits (ohne Vorzeichen): 32
Vorzeichenbehaftet: false
Ganzzahl (Integer): true
keine Rundungsfehler möglich: true
kleinster von 1 abweichender Wert: 0
PrintNumLimits<double>(); Minimum: 2.22507e-308
Maximum: 1.79769e+308
Anzahl Bits (ohne Vorzeichen): 53
Vorzeichenbehaftet: true
Ganzzahl (Integer): false
keine Rundungsfehler möglich: false
kleinster von 1 abweichender Wert: 2.22045e-016

Wie Sie der Aufstellung u.a. entnehmen können, gibt es beim unsigned long Datentyp keine Rundungsfehler (wie übrigens bei allen Integer-Datentypen) während es beim double-Datentyp (wie bei allen Gleitkomma-Datentypen) Rundungsfehler geben kann. Dies liegt darin begründet, dass wegen der internen Darstellung von Gleitkommazahlen nicht jede beliebige Zahl exakt darstellbar ist.

Übrigens: die im Beispiel verwendete Klasse numeric_limits wird später im Kurs noch ausführlicher behandelt.

sizeof() Operator

Sie können den von einem Datentyp belegten Speicherplatz (in Anzahl Bytes) mittels des Operators sizeof(DTYP) ermitteln. DTYP gibt den Datentyp an, dessen Speicherbedarf ermittelt werden soll. Wollen Sie den von einer Variablen benötigten Speicherplatz ermitteln, so geben Sie beim sizeof Operator anstelle eines Datentyps den Namen der Variablen an (2. Aufruf von sizeof im Beispiel).


short anyValue;  // short-Variable definieren
...
cout << sizeof(char) << endl;        // sizeof(datentyp)
cout << sizeof(anyValue) << endl;    // sizeof(variable)
cout << sizeof(long) << endl;        // sizeof(datentyp)

1
2
4

Die oben im Beispiel dargestellte Programmausgabe bezieht sich auf den VC++ Compiler.

Beachten Sie, dass sizeof ein Operator ist (wie z.B. +) und keine Funktion (wie z.B. sin(...) für die Sinusberechnung). Zudem ist sizeof ein Compilezeit-Ausdruck, d.h. der Compiler wird beim Übersetzen des Programms schon die Größe berechnen und entsprechende in den lauffähigen Code einsetzen. Daraus folgt, dass sizeof selbst keine zusätzliche Programmlaufzeit benötigt!