5.11 Der Datentyp »char«
Der Datentyp char kann auf zwei logisch völlig unterschiedliche Arten verwendet werden. Zum einen dient er zur Darstellung von einzelnen Zeichen wie 'a', 'A', 'b', 'B', '5', '7', '§' usw. für Tastatureingabe und Bildschirmausgabe. Zum anderen kann char genutzt werden, um kleine Ganzzahlen zu verarbeiten, wobei gesagt werden muss, dass dafür der Wertebereich relativ klein ist. Hier die Übersicht dazu:
Name | Größe | Wertebereich | Formatzeichen |
char |
1 Byte |
–128 +127 bzw. 0 255 |
%c |
Hinweis |
Ein Byte besteht nicht zwangsläufig aus 8 Bits. Es gab früher auch Maschinen, die z. B. 9 Bits als kleinsten adressierbaren Typ hatten. Des Weiteren gibt es z. B. DSPs, bei denen ein Byte 32 Bits groß ist. Damit kann ein char auch von 231 ... 231-1 gehen. Der ANSI-C-Standard schreibt hierbei nämlich nur Folgendes vor: »Alle Speicherobjekte in C müssen durch eine gleichmäßige Sequenz von Bytes mit mindestens 8 Bits Breite darstellbar sein. Ein char, egal ob jetzt signed oder unsigned, belegt exakt ein Byte.« Dies kann beispielsweise bei einer 36-Bit-Maschine bedeuten, dass ein Byte mit 9, 12, 18 oder 36 Bits definiert ist, da all diese Nummern den gleichen Teiler haben und nicht weniger als 8 Bits breit sind – und somit beide Bedingungen des ANSIC-C-Standards einhalten. Mehr zu einem Byte finden Sie hier: |
Hinweis |
Wie viele Bits ein char auf Ihrem System nun hat, ist im Makro CHAR_BIT (limits.h) definiert. Aber egal, wie viele Bits ein char hat, ein sizeof(char) muss immer eins (ein Byte) ergeben! |
An dieser Stelle will ich zum besseren Verständnis etwas weiter ausholen. Der Computer ist eigentlich dumm. Er kennt nichts anderes als die Zustände 0 für »aus« und 1 für »ein«. Dies entspricht etwa einem Lichtschalter, den Sie ein- oder ausschalten können. Im Fall von char wären dies acht Lichtschalter. Sehen wir uns dazu zuerst die mögliche Größe der Datentypen an:
Größe von char 1 Byte = 8 Bit Größe von short 2 Byte = 16 Bit Größe von int 2 oder 4 Byte = 16 Bit oder 32 Bit Größe von long 4 Byte = 32 Bit Größe von float 4 Byte = 32 Bit Größe von double 8 Byte = 64 Bit Größe von long double 10 Byte = 80 Bit
Abbildung 5.5 Einzelne Bits der Datentypen im Überblick
Betrachten Sie den Datentyp char, der ja meistens aus acht einzelnen Bits besteht. Diese acht Bits sollen nun ein Byte darstellen (wie dies am häufigsten auch anzutreffen ist) (siehe Abbildung 5.6).
Abbildung 5.6 Ein Byte (Datentyp »char«)
Jedes dieser acht Bits kann einen bestimmten Wert darstellen (siehe Abbildung 5.7).
Abbildung 5.7 Diese Zahlen ergeben sich durch die Potenzen von 2.
Der PC kann doch nur zwei Zahlen darstellen. Woher kommen dann diese Werte? Sie werden aus der Potenz von 2 berechnet (27 +26 +25 +24 +23 +22 +21 +20 ). Würden Sie jetzt hier Bit 0 und Bit 1 auf 1 setzen, also »Licht an«, würde der Wert 3 dargestellt. Dieser errechnet sich ebenfalls wieder aus den Potenzen:
0*27 +0*26 +0*25 +0*24 +0*23 +0*22 +1*21 +1*20 = 3Ein Beispiel:
Der Dezimalwert dieser Zusammensetzung der einzelnen Bits beträgt 66 (0*27 +1*26 +0*25 +0*24 +0*23 +0*22 +1*21 +0*20 = 66). Es müssen nur die einzelnen Bits zusammengezählt werden, die gesetzt (also 1) sind. Wenn Sie jetzt die ASCII-Code-Tabelle in Anhang A.2 betrachten und unter dem dezimalen Wert 66 nachsehen, stellen Sie fest, dass 66 für das große 'B' steht. Es geht nämlich hier bei char nicht um den int-Wert, sondern um das Zeichen, das diesem dezimalen Wert in der ASCII-Tabelle entspricht.
Abbildung 5.8 Dualdarstellung des dezimalen Werts 66
Die ASCII-Code-Tabelle ist eine Tabelle, an die sich alle Programmierer der Welt halten müssen. Sie enthält alle Zeichen, die der Computer darstellen kann.
Kommen wir nun nach diesem kleinen Ausflug ins Dualsystem zurück zum Thema dieses Kapitels, dem Datentyp char. Hier ein kleines Listing:
/* playing_char.c */ #include <stdio.h> int main(void) { char a = 'A'; char b = 65; int c = 65; int d; printf("a = %c\n",a); printf("b = %c\n",b); // Überrascht? printf("c = %c\n",c); // Nochmals :) d = a + b + c; // Rechenbeispiel printf("d = %d\n",d); d = 'a' + 'A'; printf("d = %d\n",d); printf("char a = %c und %d\n",a,a); printf("char b = %c und %d\n",b,b); printf("int c = %c und %d\n",c,c); return 0; }
Der Programmablauf sieht etwa folgendermaßen aus:
Abbildung 5.9 Das Programm bei der Ausführung unter Linux
Kommen wir jetzt zur Zeile:
char a = 'A';
Wenn Sie char ein Zeichen zuweisen wollen, muss es zwischen zwei einzelnen Hochkommata stehen ('A'). Folgende Varianten sind nicht möglich bzw. falsch:
// falsch, in doppelte Hochkommata == String char a = "A"; // falsch, Variablenzuweisung char a = A; /* schlechter Stil, da nicht gleich durchschaubar ist, ob der * Programmierer hier den ASCII-Buchstaben oder den * dezimalen Wert verwenden will */ char b = 65;
Hier sehen Sie auch gleich die andere Möglichkeit, char einen Wert zuzuweisen. Für den PC sind der Wert 65 und das Zeichen 'A' identisch. Beide haben dieselbe Bitdarstellung:
Abbildung 5.10 Bitdarstellung des Dezimalwerts 65 und des Zeichens ‘A‘
Dies bestätigt auch die Ausgabe im Programm:
printf("a = %c\n", a); printf("b = %c\n", b);
Auch wenn es hier so aussieht: In C gibt es keinen Datentyp, mit dem Sie echte Zeichen wie 'A', 'B' oder 'C' speichern können. Daher stehen diese Zeichen auch zwischen einzelnen Anführungszeichen. Sie geben zwar Folgendes an:
char a = 'A';
aber nach der Übersetzung des Compilers sieht dies so aus:
char a = 65;
Verwenden Sie jetzt im Programm das Formatierungszeichen %c, wird der Wert 65 anhand der ASCII-Code-Tabelle kodiert. Wird hierbei das Formatierungszeichen %d verwendet, würde dieser Wert nicht kodiert und in seiner tatsächlichen Form ausgegeben, wobei »tatsächliche Form« natürlich rein optisch gemeint ist. In Wirklichkeit wäre die tatsächliche Form eine Zahlenkolonne von Einsen und Nullen. Für den PC gelten weiterhin nur Bits und Bytes. Und wie Sie gesehen haben, funktioniert das analog auch mit dem Datentyp int.
Achtung |
Auch wenn Sie char oder unsigned char für kleine Ganzzahlwerte verwenden könnten, ist von dieser Möglichkeit abzuraten. Dies vor allem, weil in C nicht festgelegt ist, ob dieser Datentyp mit oder ohne Vorzeichen interpretiert wird. Es könnte ähnlich wie bei int auf verschiedenen Systemen zu unterschiedlichem Verhalten oder gar zu Fehlern führen (siehe Abschnitt 7.1 zu int). |
Hinweis |
Den Zeichentyp char kann man zwar auch mit signed oder unsigned spezifizieren, beachten Sie aber, dass char, unsigned char und signed char drei verschiedene Typen sind! Des Weiteren hängt es von der Compiler-Implementierung ab, ob char auch negative Zahlen aufnehmen kann. |
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.