C Forever

Coding Style Guidelines

oder - wie soll Code gut aussehen ?

Was jetzt kommt, ist ein ganz heikles Kapitel in der Programmierung.
Hier scheiden sich die Geister, jeder Programmierer hat seine ganz eigene Vorstellung, wie ein Programmtext auszusehen hat. Das beruht (meistens) nicht auf Eitelkeiten, sondern auf der jeweiligen Erfahrung, der gerade verwendeten Programmiersprache, der Unterstützung durch den Editor und/oder die IDE und vielem mehr. Dazu kommen noch Abteilungs- oder Firmen-weite Vorschriften und anderes.

Also warum überhaupt Coding Style Guidelines ?

Sagen wir es mal so: selbst, wenn man alleine vor sich hin programmiert, kann es doch sein, daß man seine früheren Arbeiten nochmal anfassen will oder als Beispiel braucht. Nichts ist dann schlimmer als den Code schon deswegen nicht mehr nachvollziehen zu können, weil man ihn aus optischen Gründen nicht mehr versteht.
Also - eine gewisse Systematik hilft beim Lesen, aber auch beim Editieren, Suchen von bestimmten Sachen im Editor, oder einfach bei der Weitergabe des Codes an andere Leute. Zu Anfang mag eine solche Systematik als Mehraufwand erscheinen. Aber spätestens, wenn man sich mal daran gewöhnt hat, läuft das meiste ganz automatisch und erleichtert die Arbeit.

Was jetzt folgt, ist meine ganz persönliche Variante von Coding Style Guidelines. Sie hat sich im Laufe von mehr als drei Jahrzehnten Programmierarbeit als nützlich herauskristallisiert.

Grundlegendes

Verwende utf-8 als Zeichencodierung

Warum?
Erstens versteht das seit Jahren jeder Editor.
Zweitens versteht das jedes Betriebssystem.
Drittens werden Sonderzeichen immer gleich dargestellt.
Somit steht die Zeichencodierung einer Zusammenarbeit über Editor- und Betriebssystemgrenzen nicht im Wege. Missverständnisse durch die Zeichendarstellung werden vermieden - Kollegen, Kunden und Geschäftsleitung freuen sich.

Sprache

In einem Projekt wird in den Quelltexten und für Dateinamen durchgehend eine Sprache verwendet.
D.h. alle Kommentare, alle Dateinamen, alle Variablen-, Konstanten- und Funktions-Bezeichner sind in derselben Nationalsprache zu halten.
Vorschlag (der einfachen Grammatik und des bildhaften Wortschatzes wegen) :
  US-Englisch

Benutze Leerzeichen statt Tabulatoren für die Einrückung

Warum?
Jede Entwicklungsumgebung, jeder Editor und jeder Programmierer hat seine eigene Vorstellung davon, wieviele Leerzeichen einem Tabulator entsprechen. Da Einrückungen die Struktur des Programmtextes verdeutlichen, sollten sie für alle Beteiligten gleich aussehen. Editoren, IDEs und dem C-Compiler ist das allerdings völlig egal. Ein Ausnahme ist GNU-Make, hier gehört die Einrückung mit Tabulator zum Sprachumfang und muss an einigen Stellen genau so erfolgen.

Um wieviel Spalten soll ich einrücken ?
Das ist Geschmackssache. Unter C-Programmieren hat sich wohl die Einrückung um jeweils 4 Spalten als Kompromiss zwischen Lesbarkeit und Zeilenlänge (Platz) herauskristallisiert.

Lesbarkeit

Das ewige Streitthema - wo kommen die Block-Klammern hin und was wird wann eingerückt ?

Die öffnende geschweifte Klammer kommt in eine neue Zeile, mit einer Einrückung. Der folgende Block ist ebenfalls um eine Stufe eingerückt. Die schließende geschweifte Klammer kommt in eine neue Zeile, mit der gleichen Einrückung.

int function test( int a )
    {
    int b;

    if( a < 10 )
        {
        b = a;
        }
    else
        {
        b = 0;
        }
    return b;
    }

Klammern bei Bedingungen

Jede Bedingung wird einzeln geklammert, auch wenn es von der Logik her nicht nötig wäre. Das erhöht die Lesbarkeit, weil man sofort sieht, was zusammengehört. Es hilft logische Fehler zu vermeiden. Und wenn der Compiler meckert, daß eine Klammer fehle oder zu viel sei, zählt man einfach nach.

if( ( c > 3 ) && ( ( d < 27 ) || ( strcmp(str, "test") == 0 ) ) || eof(f) )

Groß- und Kleinschreibung

Defines werden grundsätzlich komplett groß geschrieben. Eine Ausnahme ist allenfalls mal für ein Makro erlaubt, wenn dieses sicher wie eine Funktion verwendet werden kann.
Alle anderen Bezeichner werden niemals komplett groß geschrieben.
Von C reservierte Worte sollten immer klein geschrieben werden.

Funktionsparameter

Hat eine Funktion mehrere Parameter, werden diese durch ", " (Komma und Leerzeichen) getrennt. Durch den optischen Bruch in der Aufzählung liest sich das einfacher.

Operatoren

Operatoren werden immer von Leerzeichen eingefasst (Ausnahme vielleicht : Inkrement, Dekrement).

char c;
int i;

c = 'a' + 9;
i = 2;
i = i + 25;
// Ausnahmen ?
i++;
--i;

Suchhilfe

Funktionen

Die öffnende Klammer folgt dem Funktionsnamen ohne Leerzeichen.
Bei Deklaration und Definition steht nach der öffnenden und vor der schließenden Klammer der Parameterliste jeweils ein Leerzeichen.

double abs( double a, double b )

Beim Aufruf einer Funktion sind diese beiden Leerzeichen nicht vorhanden.

x = abs(k, l);

Sucht man also die Definition, ist der Suchstring "abs( ", sucht man auch die Aufrufe, lässt man das Leerzeichen weg.

Code auskommentieren

Da gibt es eine ganz einfache Regel : das macht man nicht!
Blockkommentare dienen NUR zum Kommentieren, also der Dokumentation.

Manchmal muss ein Code-Stück aus der Kompilierung herausgenommen werden. Dafür darf der Blockkommentar /* */ auf keinen Fall verwendet werden!
Irgendwo in dem auskommentierten Block kann sich ein Blockkommentar befinden, oder man selbst oder ein Kollege oder sonst wer fügt einen solchen ein. Dann endet der Kommentar zum Entfernen von unbenutzem Code plötzlich ganz woanders als vorgesehen. Ist der Block dann auch noch lang, findet man den Fehler nur sehr schwer. Mit Glück meckert der Compiler einen merkwürdigen Umstand, aber verlassen sollte man sich nicht darauf.
Die Ursache für diese Falle ist: C kennt keine verschachtelten Kommentare!

Einfache Lösung

Nutze bedingte Compilierung :

...
irgendwelcher Code
...
#ifdef NIX
/* auskommentierter Code
   noch mehr auskommentierter Code */
...
#endif // NIX
...
irgendwelcher Code
...

Es ist sinnvoll, der für dieses Verfahren benutzen Konstante einen immer gleichen und einprägsamen Namen zu geben. Dieser sollte auch als Zeilenkommentar hinter dem #endif stehen. Außerdem darf er nie definiert sein. Das erleichtert mindestens zwei Suchen :
1. man findet das Ende eines auskommentierten Blocks sehr einfach.
2. da solche Blöcke leicht in Vergessenheit geraten, findet man sie mit einer Suche über den gesamten Quellcode leicht wieder.

Auf den Hinweis eines Lesers noch diese Ergänzung :
Das Aus- und Einschalten des auskommentierten Codes ist mit einer einzigen Taste möglich :

© Uwe Jantzen 13.12.23