4 Grundlagen
4.1 Elemente des Quellencodes
- die Umlaute (ä, ö, ü, Ä, Ö und Ü) sowie das "ß" gehören nicht zu den erlaubten Buchstaben - Klein- und Großschreibung wird strikt unterschieden - Schlüsselwörter müssen kleingeschrieben werden - weiterhin ist folgende Konvention üblich:
- Anweisungen werden mit ; (Semikolon) abgeschlossen (Achtung: Das Vergessen des ; ist einer der häufigsten Anfängerfehler!!!) - Schlüsselwörter sind:
- oft werden auch noch:
- verwendet - Bezeichner sind Namen von Objekten (z.B. Variablen- oder Funktionsnamen). Sie dürfen aus Buchstaben, Ziffern und dem Zeichen Underline "_" bestehen, sie müssen mit einem Buchstaben oder Underline anfangen (Hinweis: Namen, die mit Underline anfangen, werden oft auf Systemebene verwendet, daher eigene Namen besser ohne führendes Underline.) - Variablennamen dürfen je nach C-Compiler unterschiedlich lang sein, man sollte sich aber bei Namen, die als Querbezug zu Programmen in anderen Quellendateien dienen, auf maximal 6 Zeichen beschränken. (Der Linker ist hier die beschränkende Komponente.) Namen, die nur programmintern auftreten haben meist 31 signifikante Stellen. - zum Zwecke der internen Dokumentation sollten Variablennamen ihren Zweck und ihre Bedeutung erkennen lassen - Beispiele für gültige Namen (links) und ungültige bzw. nicht zu empfehlende Namen (rechts):
- Kommentar kann überall dort stehen, wo auch sonst ein Trennzeichen stehen darf, er muß mit der Zeichenkombination /* eingeleitet und mit */ abgeschlossen werden (Natürlich darf Kommentar über mehrere Zeilen gehen.) - sinnvollerweise schreibt man Kommentar an das Ende einer Zeile nach einer Anweisung oder auf eine eigene Zeile - ein # in der 1.Spalte dient als Kennung für eine nachfolgende Preprozessoranweisung, diese werden vor der eigentlichen Kompilation ausgewertet, besonders wichtig sind hier: a) das Einfügen von (Header)Dateien mittels:
b) und die Definition von symbolischen Konstanten, die dann vor der eigentlichen Kompilation mittels Textersatz eingesetzt werden:
(das Wort "MAXIMUM" wird durch den Text "100" ersetzt - Preprozessoranweisungen werden nicht mit Semikolon abgeschlossen, da dieses sonst beim Textersatz mit eingefügt wird
4.2 Datentypen
In C gibt es 4 Grunddatentypen; diese sind:
Der Wertebereich für diese Grunddatentypen ist rechnerabhängig. Diese Grunddatentypen können durch Voranstellen von "Eigenschaften" noch qualifiziert werden. Wird nur eine Eigenschaft angegeben, so wird als Typ int angenommen. Die möglichen Eigenschaften sind:
Beispiele:
auto ist sozusagen die Normalbehandlung und folglich auch der Weglasswert für Variablen, die in Blöcken deklariert werden. Der Weglasswert außerhalb von Funktionen ist extern zur Erzeugung globaler Variablen. static Variablen in Funktionen behalten ihren Wert zwischen 2 Funktionsaufrufen bei, auto Variablen werden jeweils neu angelegt. Eine Besonderheit in C ist die Speicherklasse register. Damit kann man erreichen, daß Variablen (sofern es die Hardware des Rechners erlaubt) in CPU-Registern gehalten werden, was zu einer schnelleren Programmausführung führt. Beispiele für Deklarationen:
Gleichzeitig mit der Deklaration kann man die Variablen auch initialisieren:
Hinweis: Eine eingehendere Besprechung der 4 Speicherklassen wird im Zusammenhang mit Funktionen im Kapitel 6.4 vorgenommen.
Konstanten vom Typ long werden implizit gebildet, wenn die Zahl für int zu groß ist. Durch Anhängen von l oder L an die Konstante kann man eine long-Konstante erzwingen.
4.4.2 Gleitkommakonstanten Sie haben immer den Typ double. Der Dezimalpunkt und/oder die Exponentenangabe e oder E muß vorhanden sein, so wie man das gewohnt ist:
4.4.3 Zeichenkonstanten Sie haben den Typ char und werden durch Angabe eines Zeichens eingeschlossen in (einfache) Anführungszeichen erzeugt. Ihr Wert ist der numerische Wert des Zeichens im gültigen Zeichensatz (z.B. ASCII).
Nicht druckbare Zeichen können mit Hilfe des Fluchtsymbols \ (Backslash) nach folgender Tabelle angebeben werden:
ddd steht dabei für maximal 3 Oktalziffern, damit ist jedes beliebige Zeichen des Zeichensatzes darstellbar. Auch die Fluchtsymbolfolgen müssen natürlich in Anführungszeichen eingeschlossen werden. 4.4.4 Zeichenkettenkonstanten Zeichenkettenkonstanten bestehen aus einer linearen Folge von Einzelzeichen mit einem wichtigen Unterschied: Am Ende einer Zeichenkette wird immer ein NUL-Zeichen ('\0') als Endekennung automatisch angehängt. Zeichenkettenkonstanten werden in doppelte Anführungszeichen eingeschlossen. Es gelten die gleichen Fluchtsymbolfolgen wie bei Zeichenkonstanten; zusätzlich gibt es noch die Fluchtsymbolfolge \". Zeichenketten können über Zeilengrenzen gehen, wenn unmittelbar vor dem Zeilentrenner (im Quellencode) das Fluchtsymbol \ steht.
Die Modulofunktion ist nicht auf float oder double Operanden anwendbar. Die Rangfolge ist wie gewohnt: *, / und % gleich und höher als + und -. Das Minuszeichen als unärer Operator (Vorzeichen) hat einen höheren Vorrang als *, / und %. Es gibt kein positives Vorzeichen. Beispiele für die Anwendung arithmetischer Operatoren:
Höhere Rechenoperationen wie Wurzelziehen, Potenzieren, Exponentiation, usw. fehlen in C als Operator ganz; sie sind über Bibliotheksfunktionen realisiert. Bei ihrer Verwendung muß in jedem Fall die Include-Datei math.h mit eingebunden werden.
4.5.2 Vergleiche und logische Verknüpfungen Für Vergleiche stehen folgende Operatoren zur Verfügung:
Die ersten 4 haben untereinander gleichen Rang, stehen aber eine Rangstufe höher als die beiden letzten. Es gibt in C grundsätzlich keinen Datentyp BOOLEAN; WAHR oder FALSCH werden einfach über den numerischen Wert entschieden. Dabei gilt:
Beispiele für die Verwendung dieser Operatoren:
Unter die logischen Verknüpfungen fallen die Operatoren:
Sie sind hier in ihrer Rangfolge geordnet aufgeführt, logisches UND hat also einen höheren Vorrang als das logische ODER. In Ausdrücken erfolgt die Abarbeitung von links nach rechts aber nur solange, bis das Ergebnis eindeutig feststeht. Das führt zu einer kürzeren Ausführungszeit, wenn man die häufigst verwendete Bedingung an den Anfang einer Bedingungsabfrage stellt. Bei Operationen, die Nebeneffekte haben können (z.B. Inkrementation), muß man allerdings vorsichtig sein.
Diese zwei Zeilen wirken nicht gleich! 4.5.3 Inkrement- und Dekrementoperatoren C kennt spezielle Operatoren zum In- und Dekrementieren. Es sind dies:
Sie sind (wie der Vorzeichenoperator -) rechts assoziativ, werden also von rechts her zusammengefaßt. Sie können vor oder nach ihrem Operanden stehen. Im ersten Fall wird der Operand zunächst in- oder dekrementiert und dann weiterverwendet, im zweiten Fall wird der Operand erst verwendet und dann in- oder dekrementiert.
4.5.4 Bitmanipulationen C stellt auch Operatoren für Bitmanipulationen zur Verfügung. Sie können nicht auf Variablen oder Konstanten vom Typ float oder double angewendet werden. Die Operatoren sind wie folgt:
Beispiele:
und hier eine schnellere Variante:
4.5.5 Bedingte Bewertung C kennt einen Operator, der eigentlich aus einem Operatorenpaar (? :), besteht. Es handelt sich dabei um die bedingte Bewertung. Sie hat die Form:
Ist Ausdruck1 WAHR, dann wird Ausdruck2 ausgeführt, ansonsten Ausdruck3. Die bedingte Bewertung entspricht daher folgender if-else Konstruktion:
Beispiele:
Auf folgende Dinge wird hier noch einmal besonders hingewiesen: - es werden teilweise die gleichen Operatorzeichen für verschiedene Operatoren verwendet
- In- und Dekrementoperatoren haben einen sehr hohen Vorrang - die Arithmetikoperatoren haben einen Vorrang wie erwartet und gewohnt - Shifts haben einen höheren Vorrang als Vergleiche, im Gegensatz zu den anderen Bitmanipulationen, die nach den Vergleichen stehen - bitweise logische Operationen stehen vor den logischen Operationen, die sich auf ganze Zahlen beziehen - die bedingte Bewertung hat einen sehr niedrigen Vorrang, trotzdem sollte man sich bei ihrer Anwendung eine Klammerung angewöhnen, damit die Anweisung leichter lesbar ist. - außer durch den Vorrang ist die Reihenfolge der Bewertung undefiniert: z = (a * 2) + ++a kann als (a * 2)+ ++a aber auch als ++a + (a * 2) bewertet werden. Man nennt dies einen Nebeneffekt. Diese müssen aus naheliegenden Gründen vermieden werden. - ebenso ist die Reihenfolge der Bewertung von Funktionsparametern nicht gewährleistet:
- ebenfalls nicht eindeutig definiert ist folgende Konstruktion:
4.6.2 Zuweisungen - die linke Seite einer Zuweisung muß ein einfacher Ausdruck und ein sogenannter L-Wert sein - einfache Ausdrücke bezeichnen ein einzelnes Objekt, dieses Objekt kann eine Variable, eine Konstante, ein Funktionsaufruf, oder ein Feld-, Struktur-, Aufzählungs- oder Variantenelement sein. - L-Werte sind Objekte, die veränderbar sind z.B. Variablen - keine L-Werte sind: Konstanten, Feldnamen ohne folgende Indexangabe, Funktionsnamen, Namen aus einer Aufzählung, Objekte, die explizit mit const als konstant vereinbart wurden - Zuweisungen können in Ausdrücken an der Stelle eines Operanden stehen (z.B.: while ((c = getchar()) != EOF) - Zuweisungen in einer Zuweisungskette werden von rechts nach links ausgeführt:
- mit Hilfe des Kommaoperators können Listen von Anweisungen gebildet werden, sie werden von links nach rechts abgearbeitet
- Ausdruckslisten werden oft im Zusammenhang mit einer for-Schleife verwendet, um z.B. in der Reinitialisierung 2 verschiedene Operationen durchzuführen:
- Vorsicht ist allerdings dann geboten, wenn das Komma wie z.B. in einer Funktionsparameterliste noch eine andere Funktion hat, durch eine Klammerung kann man aber jederzeit das Gewünschte erreichen:
4.6.3 Datentypwandlungen - Datentypwandlungen sind immer dann notwenig, wenn 2 Operanden in einem Ausdruck verschiedene Typen haben - Datentypwandlungen werden soweit notwendig implizit durchgeführt - char wird bei Bewertungen immer in int gewandelt, dadurch sind int und char beliebig mischbar - allerdings kann die char-int Wandlung rechnerabhängig sein, char kann auf die Zahlenwerte -128 bis +127 oder 0 bis +255 abgebildet sein, die "normalen" Zeichen liegen aber immer im positiven Bereich - die char-int Wandlung ist vor allem bei der Abfrage eines eingelesenen Zeichens auf EOF wichtig (Eingelesen werden immer int Werte, die dann aber einfach char Werten zugewiesen werden können - die Wandlung von int nach long erfolgt durch Vorzeichenerweiterung (bei signed) oder Voranstellen von Nullen (unsigned), bei der umgekehrten Wandlung werden die höchstwertigen Bits einfach abgeschnitten - float wird bei Bewertungen immer in double gewandelt, alle Rechnungen erfolgen daher mit derselben großen Genauigkeit - die Wandlung von int nach float ist wohldefiniert, die umgekehrte Richtung kann rechnerabhängig sein, insbesondere bei negativen Gleitkommazahlen - den genauen Ablauf der Wandlungen bei der Auswertung eines Ausdrucks oder einer Zuweisung beschreiben folgende Regeln (übliche arithmetische Umwandlungen): zuerst werden char oder short Operanden in int Werte und float Operanden in double Werte umgewandelt hat jetzt ein Operand den Typ double, so wird der andere ebenfalls in double gewandelt und das Resultat ist auch double ist stattdesssen einer der Operanden long, so wird der andere auch in long gewandelt und das Resultat ist auch long ist andernfalls einer der Operanden unsigned, so wird auch der andere in unsigned gewandelt und das Resultat ist ebenfalls unsigned liegt keiner dieser Fälle vor, so handelt es sich um int Werte, diesen Typ hat dann natürlich auch das Resultat - durch eine sogenannte type cast Operation kann man in einem Ausdruck den Typ eines Operanden auf den geünschten Typ abändern, dies Operation ändert den Typ nur für diese eine Operation:
- einige Beispiele für implizite Typwandlungen haben wir schon in Kapitel 4.5.1 bei den Arithmetikoperatoren kennengelernt, hier sind noch einige mehr, insbesondere zur char-int Wandlung
4.6.4 Zusammengesetzte Operatoren - Eine Spezialität von C ist die abgekürzte Schreibweise für bestimmte Zuweisungen - diese abgekürzte Schreibweise ist vorteilhaft, wenn die linke Seite eine komplizierte Struktur hat (weniger Tippfehler, bessere Lesbarkeit) - bei der abgekürzten Schreibweise gilt folgendes:
ist äquivalent zu (beachten Sie die Klammern!):
- op kann einer der Operatoren: + - * / % << >> & ^ oder | sein - die Klammern sind sehr wichtig, damit keine unerwünschten Nebeneffekte auftreten:
- der Vorteil der abgekürzten Schreibweise wird an folgendem Beispiel deutlich:
|
11. November 1999, Peter Klingebiel, DVZ |