Hier nur ein paar Stichpunkte, um die gröbsten Fehler zu vermeiden: Die Empfehlungen sind nur teilweise auf C begrenzt; aber durch die vielen Freiheiten und Fehlermöglichkeiten von C wird systematisches und diszipliniertes Vorgehen schnell unentbehrlich.
Dies kann man nutzen, um möglichst viel der jeweiligen Problemlösung portabel zu schreiben.
Wo das nicht machbar ist, sollte der systemspezifische Teil so klein wie irgend möglich sein. Weiterhin empfiehlt es sich, alle Systemabhängigkeiten deutlich als solche zu kennzeichnen.
Mit #define kann man vor allem kleinere Programmänderungen schnell durchführen, wenn man die entsprechenden Konstanten rechtzeitig damit definiert.
Mit #include sollte man dafür sorgen, daß alle Deklarationen und Definitionen, die mehrere Quelltexte betreffen, nur an einer Stelle stehen und dementsprechend auch nur an einer Stelle geändert werden müssen.
Mittels bedingter Kompilierung und geschickter #define-Anweisungen kann man leicht verschiedene Versionen eines Programms verwalten: verschiedene Kunden, verschiedene Rechnerumgebungen, verschiedene Stufen der Ausgabemenge (ausführliche Protokollierung oder Fehlertests für die Entwicklung, schnellere Programmausführung für den Produktionsbetrieb), und so weiter.
Siehe dazu auch assert()
in Abschnitt 17.
Beispiel:
#include <stdlib.h> void vollelotte( char *zeiger, size_t wieviele ) { while( wieviele- ) *zeiger++ = 0; } void pfuschrum( char **zeigerzeiger ) { if( (*zeigerzeiger=realloc( *zeigerzeiger, 800 )) ) { vollelotte( *zeigerzeiger, 800 ); } else printf( "\apfuschrum(): Speicher reicht nicht!\n" ); } int main( int narg, char **args ) { char *zeig; if( (zeig=malloc( (size_t)500 )) ) { vollelotte( zeig, 500 ); pfuschrum( &zeig ); } else printf( "\amain(): Speicher reicht nicht!\n" ); }
Dagegen Achtung bei Namen, die zwischen Quelltexten über den Linker ausgetauscht werden (externe Namen)! Diese sind auf vielen (älteren) Systemen nur in den ersten 6 oder 8 Zeichen signifikant.
Möglichst unverfängliche und kollisionsfreie Namen verwenden.
Namen nicht unnötig mit einem Tiefstrich beginnen lassen.
Die meisten Funktionen kommen gut ohne goto aus; manchmal ist eine Sprungadresse (label) sinnvoll, wenn an mehreren Stellen in einer Funktion ein ähnlicher Fehler auftreten kann (womöglich in tiefgeschachtelten if-Blöcken oder Schleifen), der mehrere Anweisungen zur Folge hat. Dann springt man im Fehlerfall zu einer Sprungadresse kurz vor Ende der Funktion und geht nur an dieser einen Stelle auf den Fehler ein.
Achtung! Vor einer solchen Sprungadresse wird oft ein return vergessen, so daß die normale Programmabarbeitung auch in die Fehlerbehandlung eintritt.
Braucht man irgendwann mehr als eine Sprungadresse innerhalb einer Funktion, dann sollte man ernsthaft über die Programmstruktur nachdenken.
longjmp() ist im Programm noch wesentlich undurchsichtiger und unübersichtlicher; deshalb nur sehr überlegt einsetzen!
Beispiel:
int antwort; ... if( antwort='E' ) /* diese Zeile ist falsch! */ tuwasmitE(); else wasanderes();
Anstatt den Inhalt von antwort mit 'E' zu vergleichen, wird an antwort der Wert 'E' zugewiesen. Diese Zuweisung liefert immer ein Ergebnis ungleich 0 (nämlich 'E'). Deshalb wird prinzipiell der Teil tuwasmitE(); ausgeführt, unabhängig vom bisherigen Wert von antwort.
In allen Fällen, in denen bei einem solchen Vergleich eine Konstante (hier: 'E'), ein Rechenausdruck oder ein Funktionsaufruf steht, kann man den Fehler leicht vermeiden, indem man sich beizeiten angewöhnt, den betreffenden Operanden auf die linke Seite zu schreiben. Mit dieser Gewohnheit hätte man das zweite Gleichheitszeichen wahrscheinlich ebenfalls versehentlich wegfallen lassen, aber das Beispiel würde nun so aussehen:
int antwort; ... if( 'E'=antwort ) /* diese Zeile ist auch falsch! */ tuwasmitE(); else wasanderes();
So bekommt man wenigstens eine Fehlermeldung vom Compiler, da an die Konstante nichts zugewiesen werden darf.
Zur ungewohnten Zählweise (0 bis (n-1)) kommt bei Strings noch erschwerend hinzu, daß man für die abschließende 0 Platz vorsehen muß.
Wie geht das? Alles ausprobieren, wovon hier abgeraten wurde!
AnyWare@Wachtler.de AnyWare@Wachtler.de