char Typ

Der Typ char speichert einen ganzzahligen Wert, welcher mit 1 Byte codiert wird, was heutzutage üblicherweise 8 Bits entspricht. Ein char wird grundsätzlich zur Speicherung eines Zeichens (beispielsweise Buchstaben) verwendet.

Details

Der Name char steht für Character. Dieser Name ist verwurzelt in der Verwendung des Basis-Zeichensatzes der Sprache C, bei welchem jedes Zeichen 7 Bits Platz benötigt. Ein char muss laut Standard ein Zeichen des Basis-Zeichensatzes speichern können. Die Anzahl Bits, die hierfür benötigt werden, definiert die Einheit Byte und ist auf heutigen Computern grundsätzlich stets 8.

Früher wurde der Typ char oft wie ein winziger int verwendet (in manchen Programmiersprachen gibt es den Typ tiny int). Damit konnte ähnlich wie mit den Typ-Modifikatoren short, long oder long long festgelegt werden, wieviele Bits für eine Ganzzahl genutzt werden sollen. Heutzutage wird diese Verwendung immer seltener gesehen, da ab dem C99-Standard mit der stdint-Bibliothek viele Integer-Typen mit genaueren Angaben zur Anzahl Bits zur Verfügung stehen.

Ein char-Typ kann entweder mit signed oder unsigned modifiziert werden. Je nachdem speichert ein char entweder sowohl negative als auch positive Werte, oder aber explizit nur positive. Ob der Modifikator vor oder nach dem Typ steht, spielt keine Rolle.

char               a;
signed char        b;
char signed        c;
unsigned char      d;
char unsigned      e;

Wird der Modifikator weggelassen, wird je nach Compiler entweder signed oder unsigned angenommen. Oftmals kann ein Compiler mittels gewisser Flags dahingehend gesteuert werden, das eine oder andere zu verwenden. Durch Einbinden der limits-Bibliothek kann herausgefunden werden, was beim aktuellen Compiler der Fall ist:

#include <stdio.h>
#include <limits.h>

int main(){
  if(CHAR_MAX == SCHAR_MAX){
    printf("Char is signed\n");
  }else{
    printf("Char is unsigned\n");
  }
  return 0;
}

In der limits-Bibliothek sind alle maximal und minimal möglichen Werte eines char mit und ohne Vorzeichen-Modifikatoren definiert.

Positive Werte werden als binäre Ganzzahl gespeichert. Die negativen Werte eines signed int werden auf heutigen Computern üblicherweise mittels des Zweierkomplements codiert.

Wird durch eine arithmetische Operation der Wertebereich eines char überschritten, so wird dies als Overflow bezeichnet. Auf heutigen Prozessoren kippt dabei eine Ganzzahl mit Vorzeichen vom positiven plötzlich in den negativen Bereich und bei vorzeichenlosen Ganzzahlen folgt auf den maximalen Wert plötzlich die Zahl 0 (Null). Dies wird als Wrap-Around bezeichnet. Analog dazu wird das Unterschreiten des Wertebereiches als Underflow bezeichnet und der Wrap-Around passiert vice versa. Dass dieser Effekt jedoch auf jedem System auftritt, ist nicht garantiert.

Bei der Angabe von festen Werten im Quellcode kann das Suffix u verwendet werden, um einen festen Wert als unsigned zu kennzeichnen. Im Gegensatz zu long und long long gibt es jedoch kein Suffix, um einen festen Wert als char zu markieren. Entsprechende fest im Programmcode geschriebene Ganzzahlen haben stets mindestens den Typ int.

Heutige Compiler geben normalerweise Warnungen aus, wenn feste Werte zu gross für einen char sind.

Um einen char mit printf auszugeben oder mit scanf einzulesen, wird der Modifikator hh verwendet:


123
char c = 123;
printf("%hhd\n", c);

Arithmetische Umwandlung

Bei Zuweisungen, Initialisierungen oder Casts zu einem char-Typ werden durch den Compiler gegebenfalls arithmetische Umwandlungen durchgeführt. Im folgenden sind die Umwandlungsregeln für den char-Typ beschrieben. Bei unsicheren Umwandlungen gibt ein Compiler üblicherweise eine Warnung aus, welche jedoch bei Bedarf mittels eines expliziten Casts unterdrückt werden kann.

Bei der Umwandlung eines Fliesskomma-Typs in einen char werden die Nachkommastellen schlicht abgeschnitten (Rundung hin zu Null).

123
-123
printf("%hhd\n", (signed char) 123.456);
printf("%hhd\n", (signed char)-123.456);

Hat die umzuwandelnde Fliesskommazahl keinen Platz in einem char, so ist das Resultat undefiniert. Auf heutigen Systemen wird häufig der maximal, beziehungsweise der minimal mögliche Wert angenommen.

127
-128
255
0
printf("%hhd\n", (signed   char) 1e20);
printf("%hhd\n", (signed   char)-1e20);
printf("%hhu\n", (unsigned char) 1e20);
printf("%hhu\n", (unsigned char)-1e20);

Das Resultat kann je nach System unterschiedlich ausfallen. Die hier angegebenen Werte entsprechen den Werten auf dem System des Autors.

Bei der Umwandlung eines Integer-Typs in einen char bleiben in den wichtigsten Fällen der Wert sowie das Vorzeichen exakt erhalten:





123
-123
123
-123
unsigned  short s1 =  123;
signed    short s2 = -123;
unsigned  int   i1 =  123;
signed    int   i2 = -123;
printf("%hhu\n", (unsigned char) s1);
printf("%hhd\n", (signed   char) s2);
printf("%hhu\n", (unsigned char) i1);
printf("%hhd\n", (signed   char) i2);

Die Umwandlung eines Integer-Wertes in einen char, welcher nicht im Werteumfang enthalten ist, ist nicht definiert. Auf heutigen Systemen passiert jedoch normalerweise folgendes: Wenn der zuzuweisende Wert gleichviele oder mehr Bits besitzt, dann werden all diejenigen niederwertigsten Bits des zuzuweisenden Wertes bitgenau kopiert, welche im char-Typ Platz finden. Falls der zuzuweisende Wert weniger Bitstellen aufweist, werden die verfügbaren Bitstellen an die niederwertigsten Bitstellen des char kopiert. Die nicht-definierten höherwertigen Bit-Stellen werden folgendermassen aufgefüllt: Wenn der Typ des zuzuweisenden Wertes vorzeichenlos ist, wird an alle nicht-definierten Bit-Stellen das Bit 0 kopiert. Wenn der Typ des zuzuweisenden Wertes vorzeichenbehaftet ist, wird das höchstwertige Bit der verfügbaren Bitstellen an sämtliche höherwertige Bit-Stellen kopiert.

Durch diese Regeln können folgende Fälle zu falschen Werten führen: Eine vorzeichenbehaftete Zahl kann nicht korrekt in einen vorzeichenlosen Typ umgewandelt werden. Eine zu grosse vorzeichenlose Zahl kann bei der Umwandlung in einen vorzeichenbehafteten Typ zu negativen Werten führen. Bei der Umwandlung von (vorzeichenbehafteten oder vorzeichenlosen) Zahlen höherer Mächtigkeit (insbesondere bei short, int, long und long long) kann durch die Kürzung auf weniger Bits der Wert verfälscht werden oder gar zu falschem Vorzeichen führen.

133
-56
16
-96
printf("%hhu\n", (unsigned char) -123);
printf("%hhd\n", (signed   char)  200);
printf("%hhd\n", (signed   char)  10000);
printf("%hhd\n", (signed   char)  100000);

Ein Javascript-Programm zur Veranschaulichung der Effekte beim Abschneiden von Bits ist beim Zahlensystem-Umrechner zu finden.