C Traps and Pitfalls Sat, Jun 16. 2007
C Traps and Pitfalls, Andrew Koenig, 1988, awprofessional.com, ISBN: 0-201-17928-8.
Andrew Koenig ist in der C und C++ Welt kein Unbekannter. Er zählt zu den anerkanntesten C++ Experten weltweit und hat bis vor wenigen Jahren, wie auch Bjarne Stroustrup, in einer Forschungsabteilung von AT&T/Bell Labs (Brutstätte von C, C++, UNIX, ...) gearbeitet. Seine Rolle als Verfechter von ISO/ANSI Standards unterstützte er mit seiner Arbeit im ISO/ANSI Standardisierungsgremium für C++.
1985 hat Koenig begonnen Fallen in die C Programmierer sich immer wieder verlieren zu sammeln. Drei Jahre später wurde diese 147 Seiten umfassende Sammlung von Addison-Wesley erstmals im Taschenbuch-Format veröffentlicht. Mir liegt der neunzehnte Druck vor, wobei am Inhalt des Buches seit November 1988 nichts mehr verändert wurde. C hingegen hat sich seit den Achtzigern sehr wohl weiterentwickelt: 1989 wurde ANSI C (ANSI X3.159-1989 "Programming Language C." respektive ein Jahr später ISO/IEC 9899:1990) verabschiedet und seit 1999 (ISO/IEC 9899:1999) gibt es mit C99 wiederum einen neuen Nachfolger-Standard.
Und dennoch: Fast zwanzig Jahre nach Erscheinen dieses Buches lohnt es sich immer noch, Zeit in die Lektüre dieser Sammlung zu stecken. Nicht nur für low-level C-Programmierer. Dem Engagement Koenigs hinsichtlich Standardkonformität ist es zu verdanken, dass seine Sammlung auch wenn sie vor der Verabschiedung von ANSI C entstand, sich dennoch bereits an diesem orientiert.
Das Buch ist in 10 Abschnitte geteilt:
0 Introduction
1 Lexical pitfalls
2 Syntactic pitfalls
3 Semantic pitfalls
4 Linkage
5 Library functions
6 The preprocessor
7 Portability pitfalls
8 Advice and answers
Appendix: printf, varargs, and stdarg
In den Kapitel 1 - 3 bespricht Koenig Grundlagen, die man so auch in ähnlichen Büchern findet:
Klassiker wie das ungewollte Vertauschen von
In Kapitel 4 geht es um die Rolle des Linkers und welche Probleme beim Verlinken von Objekt Modulen auftreten können. Weitere Punkte: Die Unterschiede zwischen einer Deklaration und einer Definition, Bezeichner Konflikte und deren Auflösung (static-Modifier), und was schiefgehen kann, wenn Funktionsargumente, -parameter, Rückgabewerte und external Typinformationen durcheinander gebracht werden.
Es folgt ein kurzes Kapitel über wichtige Funktionen aus der Standard Library mit überraschenden Eigenschaften. Wie etwa:
Natürlich schlagen oder beißen so manche der beschriebenen Fallen heutzutage nicht mehr (zu). Konnte
ähnliches gilt für andere Beispiele, wie etwa: "A function called before it is defined or declared is assumed to return int."
Das stimmt für C90 kompatiblen Code, hat sich allerdings mit C99 geändert. Dennoch finde ich solche Hinweise nützlich, denn abgesehen davon, dass man etwas über die Geschichte von C erfährt, schwirrt da draußen noch sehr viel alter Code rum der gewartet werden muss.
Am Ende eines jeden Kapitels bringt Koenig Übungsbeispiele, die einerseits die besprochenen Inhalte vertiefen und anderseits zur weiteren Beschäftigung einladen sollen. Kapitel 8 enthält ausführliche Lösungen zu diesen Aufgaben, sowie allgemeine Ratschläge zur Fehlervermeidung und Tipps aus dem Alltag.
Abschließend folgt auf 13 Seiten die wohl beste und ausführlichste Behandlung über die
Wer bereits über langjährige C Erfahrungen verfügt, wird in diesem Buch nur wenig Neues erfahren. Anderseits sollte man die erste bessere C Einführung und einige praktische Erfahrungen doch schon hinter sich gelassen haben, um die Inhalte auch wirklich nachvollziehen zu können.
Seit etwa zwei Jahren gebe ich sporadisch einigen HTL Schülern C/C++ Nachhilfe. Das Ganze macht großen Spass, und ist sehr lehrreich. Ich erfahre, welche Konzepte (oft ganz unerwartet) Verständnisschwierigkeiten bereiten (z.B. Funktionsparameter) und kann zusammen mit etwas Computerarchitektur-Hintergrundwissen vermitteln, warum etwas so ist, wie es ist. An diesen Schülern habe ich eine Reihe von Beispielen aus dem Buch erproben und mit Erfolg testen können.
Koenig hat mit diesem Buch aber vor allem eines geschafft: Er hat mich wieder neugierig werden lassen. Wie reagieren und implementieren die C Umgebungen mit denen ich zu tun habe (gcc > 3 mit glibc, dietlibc sowie bedingt die libc von FreeBSD/Apple) tatsächlich? Und das ist weit mehr als ich erwarten durfte.
Müsste ich mich zwischen diesem Buch und "Expert C Programming" von Peter van der Linden entscheiden, dann würde ich letzteres wählen. Dazu jedoch etwas später mehr.
"This book belongs on your shelf if you are using C at all seriously, even if you are an expert: many of the professional C programmers who saw early drafts said things like that bug bit me just last week!"
Andrew Koenig ist in der C und C++ Welt kein Unbekannter. Er zählt zu den anerkanntesten C++ Experten weltweit und hat bis vor wenigen Jahren, wie auch Bjarne Stroustrup, in einer Forschungsabteilung von AT&T/Bell Labs (Brutstätte von C, C++, UNIX, ...) gearbeitet. Seine Rolle als Verfechter von ISO/ANSI Standards unterstützte er mit seiner Arbeit im ISO/ANSI Standardisierungsgremium für C++.
1985 hat Koenig begonnen Fallen in die C Programmierer sich immer wieder verlieren zu sammeln. Drei Jahre später wurde diese 147 Seiten umfassende Sammlung von Addison-Wesley erstmals im Taschenbuch-Format veröffentlicht. Mir liegt der neunzehnte Druck vor, wobei am Inhalt des Buches seit November 1988 nichts mehr verändert wurde. C hingegen hat sich seit den Achtzigern sehr wohl weiterentwickelt: 1989 wurde ANSI C (ANSI X3.159-1989 "Programming Language C." respektive ein Jahr später ISO/IEC 9899:1990) verabschiedet und seit 1999 (ISO/IEC 9899:1999) gibt es mit C99 wiederum einen neuen Nachfolger-Standard.
Und dennoch: Fast zwanzig Jahre nach Erscheinen dieses Buches lohnt es sich immer noch, Zeit in die Lektüre dieser Sammlung zu stecken. Nicht nur für low-level C-Programmierer. Dem Engagement Koenigs hinsichtlich Standardkonformität ist es zu verdanken, dass seine Sammlung auch wenn sie vor der Verabschiedung von ANSI C entstand, sich dennoch bereits an diesem orientiert.
Der Inhalt
Das Buch ist in 10 Abschnitte geteilt:
0 Introduction
1 Lexical pitfalls
2 Syntactic pitfalls
3 Semantic pitfalls
4 Linkage
5 Library functions
6 The preprocessor
7 Portability pitfalls
8 Advice and answers
Appendix: printf, varargs, and stdarg
"I wrote my first C program in 1977. Of course it didn't work."
In den Kapitel 1 - 3 bespricht Koenig Grundlagen, die man so auch in ähnlichen Büchern findet:
Klassiker wie das ungewollte Vertauschen von
=
mit ==
(bzw. &, |
mit &&, ||
), Greedy / Maximal Munch-Strategie (warum a---b
zu a -- - b
und nicht zu a - -- b
wird), Probleme von verschachtelten Kommentarstrukturen, Zeichenketten vs. Zeichen. Warum man sich vor Ausdrücken wie (*(void(*)())0)();
(declare it the way you use it) nicht fürchten muss; richtige Reihenfolge bei der Operatoren-Auswertung, Dangling-Else, Pointer vs. Arrays und wie man richtig zählt und sich mit asymmetrischen Grenzen viel Ärger (off-by-one errors) ersparen kann. Express a range by the first element of the range and the first element beyond it. [...] Use inclusive lower bounds and exclusive upper bounds. In Kapitel 4 geht es um die Rolle des Linkers und welche Probleme beim Verlinken von Objekt Modulen auftreten können. Weitere Punkte: Die Unterschiede zwischen einer Deklaration und einer Definition, Bezeichner Konflikte und deren Auflösung (static-Modifier), und was schiefgehen kann, wenn Funktionsargumente, -parameter, Rückgabewerte und external Typinformationen durcheinander gebracht werden.
Es folgt ein kurzes Kapitel über wichtige Funktionen aus der Standard Library mit überraschenden Eigenschaften. Wie etwa:
getchar()
liefert einen int und keinen char zurück oder der richtige Umgang mit errno
. In den nächsten beiden Kapitel dreht sich alles um Macros und auf welche Problemstellen geachtet werden muss, wenn man Software schreiben möchte, die portabel auf mehreren Architekturen unter verschiedenen Umgebungen verwendet werden soll."[...] For this reason, it is a good idea in a macro definition to enclose each parameter in parentheses. It is also important to parenthesize the entire result expression to defend against using the macro in a larger expression."
Natürlich schlagen oder beißen so manche der beschriebenen Fallen heutzutage nicht mehr (zu). Konnte
a =- 1
von frühen C Compilern noch als a = a - 1
statt a = -1
missverstanden werden, so hat sich zum einen C gewandelt, (heute: a -= 1
) und zum anderen haben sich die Compiler-Implementierungen gebessert. So sind viele der beschriebenen Compiler-Macken wie etwa a >> = 1
als legales Konstrukt oder 0195
als oktale Zahl durchgehen zu lassen, in modernen Compilern wohl kaum noch anzutreffen.ähnliches gilt für andere Beispiele, wie etwa: "A function called before it is defined or declared is assumed to return int."
Das stimmt für C90 kompatiblen Code, hat sich allerdings mit C99 geändert. Dennoch finde ich solche Hinweise nützlich, denn abgesehen davon, dass man etwas über die Geschichte von C erfährt, schwirrt da draußen noch sehr viel alter Code rum der gewartet werden muss.
Am Ende eines jeden Kapitels bringt Koenig Übungsbeispiele, die einerseits die besprochenen Inhalte vertiefen und anderseits zur weiteren Beschäftigung einladen sollen. Kapitel 8 enthält ausführliche Lösungen zu diesen Aufgaben, sowie allgemeine Ratschläge zur Fehlervermeidung und Tipps aus dem Alltag.
Exercise 2-1. C permits an extra comma in an initializer list:
int days[] = { 31, 28, 31, 30, 31, 30,Why is this useful?
31, 31, 30, 31, 30, 31, };
Exercise 5-1. When a program terminates abnormally, the last few lines of its output are often lost. Why? What can be done about it?
Abschließend folgt auf 13 Seiten die wohl beste und ausführlichste Behandlung über die
printf
-Familie, die mir je in einer nicht C-Referenz untergekommen ist und eine kurze Einführung in variable Argumentenlisten mit varargs / stdargs."Perhaps the most important avoidance technique is to know what you're doing."
Fazit
Wer bereits über langjährige C Erfahrungen verfügt, wird in diesem Buch nur wenig Neues erfahren. Anderseits sollte man die erste bessere C Einführung und einige praktische Erfahrungen doch schon hinter sich gelassen haben, um die Inhalte auch wirklich nachvollziehen zu können.
Seit etwa zwei Jahren gebe ich sporadisch einigen HTL Schülern C/C++ Nachhilfe. Das Ganze macht großen Spass, und ist sehr lehrreich. Ich erfahre, welche Konzepte (oft ganz unerwartet) Verständnisschwierigkeiten bereiten (z.B. Funktionsparameter) und kann zusammen mit etwas Computerarchitektur-Hintergrundwissen vermitteln, warum etwas so ist, wie es ist. An diesen Schülern habe ich eine Reihe von Beispielen aus dem Buch erproben und mit Erfolg testen können.
Koenig hat mit diesem Buch aber vor allem eines geschafft: Er hat mich wieder neugierig werden lassen. Wie reagieren und implementieren die C Umgebungen mit denen ich zu tun habe (gcc > 3 mit glibc, dietlibc sowie bedingt die libc von FreeBSD/Apple) tatsächlich? Und das ist weit mehr als ich erwarten durfte.
Müsste ich mich zwischen diesem Buch und "Expert C Programming" von Peter van der Linden entscheiden, dann würde ich letzteres wählen. Dazu jedoch etwas später mehr.
Posted by Wolfgang Kaufmann
in Bücher