... werden1
Das kontrolliert aber kaum ein C-Compiler; die Verantwortung dafür liegt wieder einmal beim Programmierer (die löbliche Ausnahme ist der Gnu-C/C++-Compiler g++, wenn man ihn mit der Option -Wall aufruft).
Informationen zum Wertebereich stehen in Ganzzahlige Datentypen.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
...potenz()2
Ein effektiverer Algorithmus für ganzzahlige Potenzen ist in Potenzen mit ganzzahligen Exponenten angegeben.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... abgeschlossen.3
Dies sieht auf den ersten Blick ähnlich aus wie in Pascal. In Pascal aber ist ein Semikolon nur zum Trennen der Anweisungen nötig, also nicht hinter der letzten Anweisung eines Blocks. In C dagegen wird jede vollständige Anweisung mit Semikolon abgeschlossen, also auch die letzte.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... Rechnern4
Die treibende Kraft der Moderne (mit drei blauen Buchstaben, beginnt mit I und endet mit BM) hält teilweise noch an derartigem HiTech-Gerät fest.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... ersetzt5
Der Operator ... ? ... : ... wertet den Vergleich links des Fragezeichens aus; je nach dem Ergebnis des Vergleichs wird der Wert links (wenn wahr) oder der Wert rechts des Doppelpunkts (wenn falsch) geliefert.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... enthalten6
In alten (K&R-C-Compilern war auch $) in Namen erlaubt (auch am Namensanfang); ANSI-C erlaubt dies nicht. Auch wenn die meisten Compiler es dann doch zulassen (zumindest mit Anwendung von Gewalt in Form einer Compileroption), sollte man es soweit möglich vermeiden.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... ändern7
In Einzelfällen kann man es aber: Man schreibt eine Stringkonstante und läßt einen Zeiger darauf zeigen. Über den Zeiger kann man dann bei einigen Systemen ungestraft den Inhalt der Stringkonstanten ändern; andere Systeme reagieren darauf mit einem Fehler zur Laufzeit.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
...ANSI-C8
Achtung! Nicht bei älteren C-Compilern!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... liefert9
z.B. ist qsort() aus der Standardbibliothek als void qsort(...) deklariert.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
...titelgeschichte10
Da ich selbst ausgesprochen vergeßlich bin, war diese Regel bei meinen ersten Gehversuchen in C der häufigste Grund, in [K&R II] nachzuschlagen. Daraufhin notierte ich auf dem Einband ,,0 ist false, alles andere ist true``.

Um dem Leser --Ihnen!-- diese Arbeit und meinem Werk die Verunstaltung zu ersparen, wurde dieser Satz gleich zum Titel erkoren.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
...normalisiert11
Normalisierte Gleitkommazahlen sind solche, deren binäre Mantisse mit einer 1 beginnt und die dadurch die volle Genauigkeit der Mantisse ausnutzt. Manche Rechnersysteme verwenden nur normalisierte Zahlen. Andere können durch Verwendung von ,,denormalisierten`` Zahlen auch noch Werte darstellen, die enger an der 0 liegen. Dann geht aber Genauigkeit verloren. Eine detaillierte Beschreibung ist in [DEK II] zu finden.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... schneller12
Tatsächlich hat dies kaum noch Bedeutung, weil moderne Compiler so gut optimieren, daß Hinweise des Programmierers wie register ohnehin ignoriert werden.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
...Initialisierung13
Eine illegale Möglichkeit wäre, einer Funktion die Adresse der Variable zu übergeben, wodurch die Funktion den Wert über einen Zeiger ändern kann. Beispielsweise könnte scanf() so eine const-Variable ändern. Dies muß aber nicht auf allen Systemen funktionieren!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... dahin14
heißt: bis zu der aktuellen Stelle im Quelltext
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... Feldern15
In der angelsächsischen Literatur wird das bisher bekannte Feld (zum Beispiel int f[10];) als ,,array`` bezeichnet, das hier vorgestellte Bitfeld dagegen als ,,bit field``. Zur Unterscheidung übersetzen einige Autoren den Begriff ,,array`` mit ,,Vektor``, was aber erstens nicht geläufig (da Bitfelder eine Eigenart von C sind) und zweitens bei mehrdimensionalen Feldern unpassend ist.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... bilden16
Ausnahmen: Bitfelder und Registervariablen
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... ist17
Nach dem einmaligen (!) Ausdruck feld2++ wären die Feldelemente als feld2[-1] bis feld2[8] erreichbar! Nach einem zweiten feld2++ besteht das Feld aus den Elementen feld2[-2] bis feld2[7].
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... durch18
Achtung! In diesem Beispiel wird ausdrücklich ein Feld mit 5 Elementen definiert und mit 5 Zeichen initialisiert. Dadurch wird keine abschließende Null angehängt!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... angibt19
Eine Ausnahme davon ist aber der Kernel von Unix-ähnlichen Betriebssystemen! Hier werden keine Variablen automatisch initialisiert.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... legal20
In diesem Beispiel aber natürlich unsinnig!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... weitergereicht21
Im älteren K&R-C wurde noch eine weitere automatische Umwandlung durchgeführt, und zwar wurden Strukturen übergeben als Zeiger auf die Struktur. Will man dies in ANSI-C so haben, dann muß man es explizit mit dem Adreßoperator ausdrücken.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... Fällen22
nämlich dann, wenn auf der linken Seite ein Wert steht, dem etwas zugewiesen werden kann, ein sogenannter lvalue. Einige Compiler sind so gnädig und geben in einigen Fällen wenigstens eine Warnung aus, wie etwa ,,possibly incorrect assignment``.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... Gleiche23
Natürlich hätte man stattdessen auch zwei komplette Anweisungen nehmen können.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... Anweisung24
Der Unterschied liegt nur darin, daß in der letzteren Version für den Fall, daß die Variable i vor Eintritt in die Schleife schon den Wert 0 hat, i erstmal auf -1 gesetzt und dann solange heruntergezählt wird, bis sie wieder 0 ist. Dies ist mathematisch natürlich nicht möglich, aber durch einen Überlauf in der Arithmetik meistens doch der Fall.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... fehleranfällig25
Ähnlich wie goto ist das Thema Rekursion gut geeignet, alte Feindschaften zu pflegen und neue aufbrechen zu lassen. Mehr dazu in [c't Rek.].
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... später26
Je nach System und Compiler bricht das Programm in einem solchen Fall kontrolliert mit einer Fehlermeldung ab, oder es stürzt unkontrolliert ab. Auf vernünftigen Systemen kann man zumindest durch Compileroptionen zwischen diesen beiden Möglichkeiten wählen (was dann bei einer Überprüfung etwas Laufzeiteffizienz kostet), oder (noch besser) das Betriebssystem kümmert sich automatisch darum.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... können27
Wahlspruch einiger gezwungener Pascal- und C-Programmierer ist:
,,Rekursief geht's meistens schief!``
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... lassen28
Zumindest solange die Programme portierbar bleiben sollen. Für systemnahe Probleme sind sie nach wie vor noch manchmal sinnvoll, aber dann nicht mehr rechnerunabhängig.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... CLASS="sans">stdio.h29
Anders als zur Übergabe an Funktionen sollte dieser Zeiger nicht verwendet werden; insbesondere darf man die Struktur, auf die er zeigt, nicht manipulieren!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... definiert30
Zum Unterschied zwischen Definition und Deklaration siehe Abschnitt 3 auf Seite [*].
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... wurde31
Interessant ist daran, daß nicht nur das Programm mit einer Fehlermeldung abgebrochen wird, sondern auch die Stelle im Quelltext und der Wortlaut der verletzten Bedingung (!) ausgegeben wird. Dies ist allein durch den Praeprozessor möglich! Wer das trivial findet, kann zur Übung das Makro assert() selbst schreiben, ohne in assert.h zu spicken.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... aus.32
Eventuelle Ähnlichkeiten mit dem realen Straßenverkehr sind rein zufällig.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... Programm33
Der hier gezeigte Quelltext ist naturgemäß kein Musterbeispiel an Lesbarkeit und Übersichtlichkeit. Zur Nachahmung ist dieser Stil sicher nicht empfohlen!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
...cp[1]34
++ hat eine höhere Priorität als *! Siehe Operatoren und Ausdrücke.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
...c[2]35
Ausdrücke mit dem Operator * werden von rechts her zusammengefaßt, siehe auch Seite [*]. Deshalb wird erst der rechte * verwendet, dann der linke.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
...errno36
Nach dem #includen der Datei errno.h kann man errno wie eine als extern int vereinbarte Variable verwenden; tatsächlich ist errno meistens als Makro mit einem versteckten Funktionsaufruf definiert.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... teilen37
CLOCKS_PER_SEC hieß in einem vorläufigen Entwurf der Normung CLK_TCK; diese Bezeichnung ist bei manchen Compilern noch anzutreffen. Um mit einem solchen Compiler aber portable Programme erstellen zu können, sollte man in diesem Fall trotzdem CLOCKS_PER_SEC verwenden und die Headerdatei time.h durch Anfügen von
#define CLOCKS_PER_SEC CLK_TCK
auf den neuesten Stand bringen.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... Inhalt38
nicht so bei calloc(), siehe dort.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
... gebildet39
In der stillen Hoffnung, daß der resultierende Name nicht anderweitig vergeben wird.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.