C-Programmierung: Programmierstil

Aus Wikibooks

Ein gewisser Programmierstil ist notwendig, um anderen Programmierern das Lesen des Quelltextes nicht unnötig zu erschweren und um seinen eigenen Code auch nach langer Zeit noch zu verstehen.

Außerdem zwingt man sich durch einen gewissen Stil selbst zum sauberen Programmieren, was die Wartung des Codes vereinfacht.

Kommentare[Bearbeiten]

Grundsätzlich sollten alle Stellen im Code, die nicht selbsterklärend sind, bestimmtes Vorwissen erfordern oder für andere Stellen im Quelltext kritisch sind, kommentiert werden. Kommentare sollten sich jedoch nur darauf beschränken, zu erklären, WAS eine Funktion macht, und NICHT WIE es gemacht wird.

Eine gute Regel lautet: Kann man die Funktionalität mit Hilfe des Quelltextes klar formulieren so sollte man es auch tun, ansonsten muss es mit einem Kommentar erklärt werden. Im Englischen lautet die Regel: If you can say it with code, code it, else comment.

Globale Variablen[Bearbeiten]

Globale Variablen sollten vermieden werden, da sie ein Programm sehr anfällig für Fehler machen und schnell zum unsauberen Programmieren verleiten.

Wird eine Variable von mehreren Funktionen innerhalb derselben Datei verwendet, ist es hilfreich, diese Variable als static zu markieren, so dass sie nicht im globalen Namensraum auftaucht.

Goto-Anweisungen[Bearbeiten]

Die goto-Anweisung ist unter Programmierern verpönt, weil sie ein Programm schlecht lesbar machen kann, denn sie kann den Programmlauf völlig zusammenhanglos an jede beliebige Stelle im Programm verzweigen, und so genannten Spaghetti-Code entstehen lassen.

Sie lässt sich fast immer durch Verwenden von Funktionen und Kontrollstrukturen, man nennt dies strukturiertes Programmieren, vermeiden. Es gibt dennoch Fälle, wie z.B. das Exception-Handling mit errno, welche mit Hilfe von goto-Anweisungen leichter realisierbar und sauberer sind.

Generell sollte für saubere Programmierung zumindest gelten, dass eine goto-Verzweigung niemals außerhalb der aktuellen Funktion erfolgen darf. Außerdem sollte hinter der Sprungmarke eines gotos kein weiteres goto folgen.

Namensgebung[Bearbeiten]

Es gibt viele verschiedene Wege, die man bei der Namensgebung von Variablen, Konstanten, Funktionen usw. beschreiten kann. Zu beachten ist jedenfalls, dass man, egal welches System man verwendet (z.B. Variablen immer klein schreiben und ihnen den Typ als Abkürzung voranstellen und Funktionen mit Großbuchstaben beginnen und zwei Wörter mit Großbuchstaben trennen oder den Unterstrich verwenden), konsequent dabei bleibt. Bei der Sprache, die man für die Bezeichnungen wählt, sei aber etwas angemerkt. Wenn man Open-Source programmieren will, so bietet es sich meist eher an, englische Bezeichnungen zu wählen; ist man aber in einem Team von deutschsprachigen Entwicklern, so wäre wohl die Muttersprache die bessere Wahl. Aber auch hier gilt: Egal was man wählt, man sollte nach der Entscheidung konsequent bleiben.

Da sich alle globalen Funktionen und Variablen einen Namensraum teilen, macht es Sinn, etwa durch Voranstellen des Modulnamens vor den Symbolnamen Eindeutigkeit sicherzustellen. In vielen Fällen lassen sich globale Symbole auch vermeiden, wenn man stattdessen statische Symbole verwendet.

Es sei jedoch angemerkt, dass es meistens nicht sinnvoll ist, Variablen mit nur einem Buchstaben zu verwenden. Es sei denn, es hat sich dieser Buchstabe bereits als Bezeichner in einem Bereich etabliert. Ein Beispiel dafür ist die Variable i als Schleifenzähler oder e, wenn die Eulersche Zahl gebraucht wird. Code ist sehr schlecht zu warten wenn man erstmal suchen muss, welchen Sinn z.B. a hat.

Verbreitete Bezeichner sind:

h, i, j, k
Laufvariablen in Schleifen (i: index)
w, x, y, z
Zeilen, Spalten, usw. einer Matrix
r, s, t
Zeiger auf Zeichenketten
rv
Rückgabewert (return value)
sp
Stack Pointer bei Array
cnt
Zählervariable
tmp
Variable, die nur sehr kurz verwendet wird (temporary)

Gestaltung des Codes[Bearbeiten]

Verschiedene Menschen gestalten ihren Code unterschiedlich. Die Einen bevorzugen z.B. bei einer Funktion folgendes Aussehen:

int funk(int a){
    return 2 * a;
}

andere wiederum würden diese Funktion eher so

int funk (int a)
{
  return 2 * a;
}

schreiben. Es gibt vermutlich so viele unterschiedliche Schreibweisen von Programmen, wie es programmierende Menschen gibt und sicher ist der Eine oder Andere etwas religiös gegenüber der Platzierung einzelner Leerzeichen. Innerhalb von Teams haben sich besondere Vorlieben herauskristallisiert, wie Code auszusehen hat. Um zwischen verschiedenen Gestaltungen des Codes wechseln zu können, gibt es Quelltextformatierer, wie z.B.: GNU indent, Artistic Style und eine grafische Oberfläche UniversalIndentGUI, die sie bequem benutzen lässt.

Standard-Funktionen und System-Erweiterungen[Bearbeiten]

Sollte man beim Lösen eines Problem nicht allein mit dem auskommen, was durch den C-Standard erreicht werden kann, ist es sinnvoll die systemspezifischen Teile des Codes in eigene Funktionen und Header zu packen. Dieses macht es leichter den Code auf einem anderen System zu reimplementieren, weil nur die Funktionalität im systemspezifischen Code ausgetauscht werden muss.