2. Zeichen, Zeichensätze und Tokens
2.1. Zeichen
  Ein C-Programm ist eine Folge von Zeichen aus einem Zeichensatz. Üblicherweise werden
  dabei folgende Zeichen verwendet:
      1. Die 52 Groß- und Kleinbuchstaben:
           A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
           a b c d e f g h i j k l m n o p q r s t u v w x y z
      2. Die 10 Ziffern:
           0 1 2 3 4 5 6 7 8 9
      3. Das Leerzeichen
      4. Der horizontaler und der vertikaler Tabulator sowie der Seitenvorschub
      5. Die folgenden 29 Zeichen:
           ! " % & ( ) = . , : ; + - * / # ~ { } [ ] < > | ’ _ \ ? ^
  Zusätzlich wird ein Zeichen oder eine Zeichenfolge benötigt, die das Ende der
  Programmzeilen angibt. Alle weiteren Zeichen (z.B. für die Formatierung des Quelltextes)
  werden als Leerzeichen angesehen und beeinflussen den Quelltext in keiner Weise.
  
2.2. Zeichensatz im ausführenden Programm
  Der Zeichensatz, der für das Programm während der Ausführung verwendet wird,
  muss nicht identisch sein mit dem Zeichensatz, der für die Eingabe der Quelltexte
  verwendet wird. Daher kann es bei der Ein- und Ausgabe zu unerwünschten Effekten kommen.
  So werden z.B. bei einem Konsolen-Programm, das unter MS Windows eingegeben und in einem
  DOS-Fenster ausgeführt wird, die deutschen Umlaute in der Bildschirmausgabe nicht korrekt
  angezeigt.
  Um diese Probleme zu umgehen, müssen diese Zeichen als ASCII-Werte (oktal) in den Quelltext
  eingegeben werden.
  Beispiel:
   kap02_01.c
  kap02_01.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    printf("Deutsche Umlaute\n\n");
  06 
  07    printf("Linux-Konsole (ISO-8859):\n");
  08    printf("ae = \344\n");
  09    printf("oe = \366\n");
  10    printf("ue = \374\n\n");
  11 
  12    printf("DOS-Eingabeaufforderung:\n");
  13    printf("ae = \204\n");
  14    printf("oe = \224\n");
  15    printf("ue = \201\n\n");
  16 
  17    return 0;
  18 }
  
2.3. Weiße Leerzeichen und Zeilenende
  In einem C-Programm werden das Leerzeichen, das Zeilenende, der horizontale und der vertikaler
  Tabulator und der Seitenvorschub als Weiße Leerzeichen (White Spaces) bezeichnet. Auch
  Kommentare werden wie weiße Leerzeichen behandelt (siehe Abschnitt Kommentare).
  Diese Zeichen werden ignoriert, da sie nur zum Trennen von benachbarten Tokens dienen - mit
  Ausnahme, wenn diese Zeichen in konstanten Zeichen bzw. Zeichenketten stehen.
  Weiße Leerzeichen werden im allgemeinen verwendet, um ein C-Programm für uns Menschen
  lesbarer zu machen (siehe Kapitel Gestaltung von C-Programmen).
  Das Zeilenende-Zeichen bzw. -Zeichenfolge markiert das Ende einer Quelltextzeile. Manche
  C-Compiler interpretieren die Eingabetaste, den Seitenvorschub und den vertikalen Tabulator
  auch als Ende einer Quelltextzeile. Dies ist wichtig für das Erkennen, wann eine
  Präprozessorzeile (siehe Kapitel Präprozessorbefehle) zu Ende ist.
  Eine Quelltextzeile kann in der nächsten Editor-Zeile fortgeführt werden, wenn sie mit
  einem Backslash ('\') oder mit dem Trigraph '??/'
  (siehe nächsten Abschnitt Trigraphen) beendet wird. Im C99-Standard lassen sich damit
  sogar Tokens aufsplitten. Beim Compilieren wird der Backslash bzw. der Trigraph samt
  Zeilenende beseitigt, um eine längere, logisch zusammenhängende Zeile zu erzeugen.
  Dies geschieht nach dem Konvertieren der Trigraphen und der Multibyte-Zeichen, aber noch vor
  dem Präprozessor und dem eigentlichen Compiliervorgang.
  Beispiel:
  Die Zeilen
  
  if (a == b) x = 1; el\
  se x = 2;
  
  werden umgewandelt in
  
  if (a == b) x = 1; else x = 2;
  
  Viele C-Compiler lassen nur eine bestimmte Länge für die Quelltextzeilen - vor und
  nach dem Umwandeln - zu. Der C89-Standard erlaubt logische Zeilen bis maximal 509 Zeichen,
  der C99-Standard bis maximal 4.095 Zeichen.
  
2.4. Trigraphen
  Mit dem Standard-C wurden einige Zeichenfolgen eingeführt, mit denen wichtige Zeichen
  dargestellt werden können, auch wenn der Quelltext mit einem Zeichensatz geschrieben wird,
  der diese Zeichen nicht beinhaltet. Da diese Zeichenfolgen immer aus drei Zeichen bestehen,
  werden diese auch Trigraphen genannt. Trigraphen werden auch in konstanten Zeichenfolgen
  erkannt und umgesetzt. Das Umwandeln der Trigraphen erfolgt beim Aufruf des Compilers als erstes,
  sogar noch vor dem Präprozessor. Es gibt genau neun Trigraphen, alle anderen Zeichenfolgen,
  die mit zwei Fragezeichen beginnen, werden nicht verändert.
  
| Trigraph | Ersetzt | Trigraph | Ersetzt | |
| ??( | [ | ??) | ] | |
| ??< | { | ??> | } | |
| ??/ | \ | ??! | | | |
| ??' | ^ | ??- | ~ | |
| ??= | # | |||
  Beispiel:
  Um eine konstante Zeichenfolge mit einem Backslash auszugeben, müssen zwei aufeinander
  folgende Backslashs geschrieben werden. Jeder dieser Backslash kann wieder in einen
  Trigraphen umgesetzt werden. Daher wird mit der Zeichenfolge "??/??/"
  ein Backslash "\" ausgegeben.
  Um zu verhindern, dass eine Zeichenfolge als Trigraph interpretiert wird, muss das zweite
  Fragezeichen durch '\?' ersetzt werden. Um die Zeichenkette
  "Wer??!" zu erhalten, muss also "Wer?\?!" eingegeben
  werden.
   kap02_02.c
  kap02_02.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    printf("Trigraphen:\n\n");
  06 
  07    printf("Backslash: ??/??/\n");
  08    printf("Wer??!   oder   Wer?\?!\n");
  09 
  10    return 0;
  11 }
  
  Bei manchen Compiler muss explizit angegeben werden, dass Trigraphen verwendet werden. Zum Beispiel
  muss beim GNU-C-Compiler gcc zusätzlich die Option -trigraphs
  angegeben werden.
  
2.5. Multibytes und Wide Characters
  Mit C95 wurden die Multibytes und Wide Characters eingeführt. Damit können auch
  Zeichensätze verwendet werden, die mehr als 256 Zeichen beinhalten. Auf diese
  speziellen Zeichen wird im Kapitel Datentypen in C weiter eingegangen.
  
2.6. Kommentare
  Kommentare werden vom Compiler komplett ignoriert, d.h. sie werden wie weiße
  Leerzeichen behandelt. Kommentare sollen zum Verständnis des Quelltextes dienen bzw.
  dem Leser wichtige Hinweise geben.
  Ein Kommentar beginnt mit den zwei Zeichen /* und endet mit den zwei
  Zeichen */. Dazwischen können beliebig viele Zeichen -
  einschließlich Zeilenumbrüche - stehen. Im Standard-C können Kommentare
  nicht geschachtelt werden.
  In C99 wurden zusätzlich Zeilenkommentare eingeführt. D.h. ein Kommentar kann
  auch mit // beginnen. Dieser Kommentar endet dann automatisch am Ende
  der Zeile.
  Kommentare werden nicht innerhalb von konstanten Zeichen oder Zeichenketten - also innerhalb
  von Anführungszeichen - erkannt.
  Kommentare werden noch vor dem Präprozessor entfernt, so dass Präprozessorbefehle
  innerhalb von Kommentaren nicht erkannt werden können. Auch haben Zeilenumbrüche
  innerhalb von Kommentaren keinerlei Auswirkungen auf die Programmzeile, in der der Kommentar
  steht.
  Standard-C schreibt vor, dass alle Kommentare durch ein einzelnes Leerzeichen ersetzt werden
  sollen. Einige ältere Compiler löschen wohl die Kommentare, aber setzen dafür
  kein Leerzeichen ein. Dies kann fatale Folgen haben, da ohne Leerzeichen die Texte vor und
  hinter dem Kommentar nahtlos zusammengeschrieben werden.
  Kommentare sollten nicht dafür genutzt werden, um größere Programmteile
  auszukommentieren. Denn ist in diesem Programmteil selber wieder ein Kommentar
  (geschachtelte Kommentare; siehe oben), wird nicht wirklich das ganze Programmteil
  auskommentiert. Ein Compilerfehler ist die Folge.
  
2.7. Tokens
  Die Zeichen, aus denen das C-Programm besteht, werden in sogenannten Tokens unterteilt. Es
  gibt fünf Gruppen von Tokens: Operatoren, Trennzeichen, Bezeichner,
  Schlüsselwörter und Literale.
  Benachbarte Tokens werden am besten durch weiße Leerzeichen getrennt. Vor und nach
  Operatoren müssen keine weißen Leerzeichen stehen; der Compiler setzt dann von
  links nach rechts immer die längstmöglichen Tokens zusammen, auch wenn das Ergebnis
  kein gültiges C-Programm mehr ist. Von daher sollten auch hier weiße Leerzeichen
  verwendet werden.
  Beispiele:
  In der folgenden Tabelle werden verschiedene Zeichenfolgen und deren Erkennung in
  C-Tokens dargestellt. Dabei werden die einzelnen erkannten C-Tokens mit einem Komma
  getrennt.
  
| Zeichenfolge | C-Tokens | 
| forwhile | forwhile | 
| b>x | b, >, x | 
| b->x | b, ->, x | 
| b--x | b, --, x | 
| b---x | b, --, -, x | 
  Im ersten Beispiel werden die Schlüsselwörter for und
  while nicht als einzelne Tokens erkannt, da sie nicht mit einem
  weißen Leerzeichen getrennt wurden.
  Das vierte Beispiel erzeugt einen Fehler beim Compilieren, da hier die Tokens falsch erkannt
  werden. Richtig erkannt werden sie erst mit dem Einsetzen von weißen Leerzeichen:
  b - -x. Dann wird nämlich das erste Minuszeichen als Operator
  für die Subtraktion und das zweite Minuszeichen als Vorzeichen für die
  Variable x erkannt.
  Das fünfte Beispiel ist für den Leser nicht klar: Es kann
    b-- - x   oder   b - --x  
  gemeint sein. Erst durch die Regel, dass von links nach rechts immer die
  längstmöglichen Tokens erkannt werden, macht klar, dass der Compiler
  tatsächlich die erste Variante erkennt. Wird die zweite Variante gewünscht,
  müssen entsprechende weiße Leerzeichen eingefügt werden.
  
2.8. Operatoren und Trennzeichen
  Die im Standard-C gültigen Operatoren und Trennzeichen sind in der folgenden Tabelle
  aufgelistet. Um Programmierer zu unterstützen, deren Tastatur die geschweiften und
  eckigen Klammern und die Raute (#) nicht enthalten, können auch
  die alternativen Schreibweisen verwendet werden: <%,
  %>, <:, :>,
  %: und %:%:.
  Im traditionellen C werden die zusammengesetzten Zuweisungsoperatoren als zwei seperate
  Tokens erkannt - nämlich als Operator und als Gleichheitszeichen. Hier dürfen also
  auch weiße Leerzeichen zwischen Operator und Gleichheitszeichen verwendet werden.
  Im Standard-C dagegen werden die zusammengesetzten Zuweisungsoperatoren als ein einzelnes
  Token erkannt; entsprechend dürfen im Standard-C keine weißen Leerzeichen zwischen
  Operator und Gleichheitszeichen eingefügt werden.
  
| Bezeichnung | Tokens | 
| Einzelne Operatoren | ! % ^ & * - + = ~ | . < > / ? | 
| Zusammengesetzte Zuweisungsoperatoren | += -= *= /= %= <<= >>= &= ^= |= | 
| Andere zusammengesetzte Operatoren | -> ++ -- << >> <= >= == != && || | 
| Trennzeichen | ( ) [ ] { } , ; : ... | 
| Alternative Schreibweise für Trennzeichen | <%     (geschweifte Klammer auf) %> (geschweifte Klammer zu) <: (eckige Klammer auf) :> (eckige Klammer zu) %: (Raute) %:%: (zwei Rauten hintereinander) | 
  Beispiel:
   kap02_03.c
  kap02_03.c
  
  01 %:include <stdio.h>
  02 
  03 int main()
  04 <%
  05    int Array<:10:> = <% 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 %>;
  06 
  07    printf("Array[5] = %i\n", Array<:5:>);
  08 
  09    return 0;
  10 %>
  
  Die alternativen Schreibweisen für Trennzeichen werden nicht von allen Compilern unterstützt.
  
2.9. Bezeichner
  Bezeichner sind Namen für Konstanten, Variablen, Datentypen, Klassen, Funktionen oder
  Makros. Sie bestehen aus einer Folge von Buchstaben, Ziffern und dem Unterstrich; sie
  dürfen allerdings nicht mit einer Ziffer beginnen und dürfen keine
  Schlüsselwörter sein. Dabei wird bei den Buchstaben zwischen
  Groß- und Kleinschreibung unterschieden, d.h. die Bezeichner abc
  und ABC sind zwei unterschiedliche Bezeichner.
  Seit C99 dürfen Bezeichner auch andere universelle oder systemabhängige
  Multibyte-Zeichen beinhalten. Diese dürfen wie die Ziffern nicht als erstes Zeichen
  verwendet werden und müssen ähnlich wie Buchstaben sein. Eine Liste der für
  Bezeichner erlaubten Zeichen ist im C99-Standard ISO/IEC 9899: 1999 und im ISO/IEC TR
  10176-1998 zu finden. Darauf wird in diesem Skript nicht weiter eingegangen.
  Neben den Schlüsselwörtern muss man aufpassen, nicht einen Bezeichner der
  Standard-Bibliotheken doppelt zu verwenden. Viele dieser Bezeichner fangen mit einem
  Unterstrich an, gefolgt von entweder einem zweiten Unterstrich oder einem
  Großbuchstaben. Daher sollten keine Bezeichner verwendet werden, die mit einem
  Unterstrich beginnen.
  Während Bezeichner im Prinzip beliebig lang sein dürfen - sie dürfen maximal so lang
  sein, wie eine Programmzeile lang sein darf -, wird nur eine bestimmte (signifikante)
  Anzahl von Zeichen zur Unterscheidung der Bezeichner verwendet. Vor dem C89-Standard
  betrug sie manchmal nur 8 Zeichen (Compilerabhängig; schließlich gab es damals
  noch keinen Standard), im C89-Standard betrug sie mindestens 31 Zeichen und im C99-Standard
  mindestens 63 Zeichen.
  Beispiel:
  Vor dem C89-Standard waren für einen Compiler die beiden Bezeichner
  LangerBezeichner und LangerBezeichnerNeu identisch,
  da nur die ersten 8 Zeichen zur Unterscheidung verwendet wurden.
  Für externe Bezeichner - also Bezeichner, die mit dem Schlüsselwort
  extern deklariert werden - gelten weitere Einschränkungen, da
  diese Bezeichner unter Umständen auch von anderen Compilern, Linkern oder Debugger,
  die stärkere Begrenzungen haben, bearbeitet werden müssen. So fordert der
  C89-Standard vom Compiler, dass externe Bezeichner eine maximale Länge von mindestens 6 Zeichen
  haben dürfen. Der C99-Standard hat dies auf mindestens 31 Zeichen erweitert.
  
2.10. Schlüsselwörter
  Die Bezeichner, die in der folgenden Tabelle aufgelistet werden, sind
  Schlüsselwörter (engl. keywords) und dürfen anderweitig nicht als
  Bezeichner (z.B. als Variablen) verwendet werden. Schlüsselwörter dürfen
  aber als Präprozessor-Makronamen verwendet werden, da der Präprozessor diese
  Makronamen umsetzt bevor der Compiler mit der Erkennung der Schlüsselwörter
  beginnt.
  
| auto | _Bool 1 | break | case | char | _Complex 1 | 
| const | continue | default | do | double | else | 
| enum | extern | float | for | goto | if | 
| _Imaginary 1 | inline 1 | int | long | register | restrict 1 | 
| return | short | signed | sizeof | static | struct | 
| switch | typedef | union | unsigned | void | volatile | 
| while | 
  1 Diese Schlüsselwörter sind erst im C99-Standard enthalten. Davon ist
  aber nur das Schlüsselwort inline auch in C++ ein
  Schlüsselwort!
  Mit dem C11-Standard sind noch folgende Schlüsselwörter dazu gekommen:
  
| _Alignas | _Alignof | _Atomic | _Generic | 
| _Noreturn | _Static_assert | _Thread_local | 
  Zusätzlich haben einige Compiler als Spracherweiterung die Schlüsselwörter
  asm (Schlüsselwort in C++) und fortran. Ferner
  sind in der Headerdatei iso646.h die Makros
  and, and_eq, bitand,
  bitor, compl, not,
  not_eq, or, or_eq,
  xor und xor_eq definiert, die in C++ zu den
  Schlüsselwörter gehören.
  
2.11. Literale
  Es gibt vier verschiedene Arten von Literalen (engl. literals): Ganze Zahlen,
  Fließkommazahlen, Zeichen und Zeichenketten. Manchmal werden Literale auch
  fälschlicherweise "Konstante" genannt; sie müssen aber von den unveränderlichen
  Variablen, Konstanten und Datentypen unterschieden werden.
  Jedes Literal ist gekennzeichnet durch Wert und Datentyp. Die Formate der verschiedenen
  Literale werden im Kapitel Datentypen in C vorgestellt.
  
  Voriges Kapitel: 1. Einführung
  
Nächstes Kapitel: 3. Variablen

