- ... 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.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.