maettig.com

Thiemos Archiv

Ich wurde auf den lehrreichen Artikel »The Top 10 Ways to get screwed by the C programming language« hingewiesen und habe im Folgenden versucht, meine mit der Zeit erarbeiteten Regeln zur Vermeidung solcher Fehler zu notieren. Habe ich etwas vergessen oder durcheinander gebracht?
  1. Nicht abgeschlossene Kommentarblöcke sind in jedem Editor mit Syntax-Highlighting leicht aufzufinden.
  2. Das Vertauschen der Zuweisung = und des Vergleichsoperators == ist in sehr vielen Programmiersprachen ein Problem. Oft wird empfohlen, wann immer möglich den konstanten Ausdruck an die erste Stelle zu schreiben, also z.B. if ("C" == sprache) anstatt des gewohnten if (sprache == "C"). Tippfehler wie in "C" = sprache lässt der Compiler nämlich nicht zu.
  3. Der Denkfehler im gezeigten Beispiel ist, dass b keine Variable sondern ein Platzhalter ist. Dem Casting-Operator muss also unbedingt eine Klammer folgen: a = (char)(b).
  4. Die Möglichkeit, mit #define Sprachkonstrukte umzudefinieren, war schon immer tödlich: #define + -. Das ist tatsächlich ein Fehler in der Sprache, wenn man so will.
  5. Wenn der Compiler sich nicht mit »nicht alle Programmpfade geben einen Wert zurück« meldet, sollte man über einen Wechsel nachdenken.
  6. Dass der Wechsel der »Endian«-Eigenschaft diverse Seiteneffekte mit sich bringt, soll offenbar ein »Feature« der Sprache sein, das man auf die eine oder andere Art wahrscheinlich sogar umgehen kann.
  7. Wer so etwas Fehlerträchtiges konstruiert und sich auf die Abarbeitungsreihenfolge von Funktionsparametern verlässt, hat es ehrlich nicht besser verdient.
  8. Es ist zu empfehlen, die zu if, while usw. gehörenden geschweiften Klammern grundsätzlich zu setzen, auch wenn sie nur eine einzige Codezeile beinhalten. Außerdem ist die Schreibweise vorzuziehen, bei der die Klammern ausgerichtet untereinander stehen. Das beansprucht zwar jedesmal ein bis zwei Zeilen mehr, ist aber ganz erheblich übersichtlicher.
  9. Manchmal ist C wirklich merkwürdig.
  10. Die Variable wird verworfen, sobald ihr Gültigkeitsbereich (Scope) verlassen wurde. Korrekt wäre es, den benötigten Speicher mit malloc dauerhafter zu reservieren.
  11. Merkwürdig ist das schon, da man annehmen sollte, dass der Präfixoperator ++ zu allererst ausgeführt wird. Aber auch hier gilt: Wer etwas so Fehleranfälliges schreibt, hat es nicht anders verdient.
  12. Ein vernünftiger Compiler zeigt uninitialisierte Variablen an. Spätestens ein schrittweiser Durchlauf mit dem Debugger dürfte schnell zeigen, dass b einen ganz merkwürdigen Wert beinhaltet.
  13. Auch hier genügt ein einfacher Debugger-Durchgang, um den tatsächlichen Wert der vermeintlichen Konstante anzuzeigen.
  14. Typisch für C.
  15. Seltsam, aber wahr. Die Obergrenze eines Arrays wird nirgends implizit notiert, das muss man selbst tun.
  16. Die Interpretation von z.B. 010 als Oktalzahl sorgt immer wieder für Erstaunen, weil dieses »Feature« der Sprache praktisch nie benötigt wird. Hier hilft nur eine gute Kenntniss der Sprache und sorgfältiges Debuggen.
  17. Dass es vorzeichenbehaftete Zeichen (Char) gibt, ist wirklich seltsam. Auch hier ist es ganz einfach wichtig, seine Sprache zu kennen.
Ich will jetzt nicht die ganze Liste durchgehen, deshalb nur kurz:
zu 2.) Guter Tipp.
Zu 4.) Eine Präprozessordirektive mit einem Semikolon abzuschließen ist in (fast) jedem Fall tödlich. ;)
tom
1) Generell ist das ein Problem, wenn man Kommentare z.B. zu Testzwecken verschachtelt. Viele Editoren können aber komplette Blöcke auf einmal kommentieren und auskommentieren, so daß der C++-Zeilenkommentar besser geeignet ist

2) Nette Idee, stört aber die Lesbarkeit. Und das es keinen boolschen Datentyp in C gibt sollte eigentlich jeder C-Nutzer wissen...

3) Allgemein sind C++-Erweiterungen wie typisierte Konstanten und Inlinefunktionen dem Preprozessor vorzuziehen.

8) Wer auf Klammern verzichtet sollte sich bewußt sein, daß der Block nur aus einer Zeile besteht. Besserer Styleguide: Wenn auf Klammern verzichtet wird, die komplette Bedingung samt auszuführendem Block in eine Zeile setzen.

10) Bei den Standarddatentypen gibts nun einmal weder GarbageCollection noch Referenzzähler, das gehört ebenfalls zum Basiswissen.

13) Das ist nun einmal der Preis dafür, wenn man nicht explizit nichtlokale Bezeichner via global, uplevel, etc. importieren will. Läßt sich vermeiden, indem man nicht für jeden Kram dieselben 08/15-Bezeichner verwendet.

14) Seit C99 gibt es weitere Datentypen mit garantierter Bitzahl bzw. garantierter minimaler Bitzahl.

15) Arrays in C sind nun einmal genau wie Strings nichts anderes als Zeiger. Auch das ist Basiswissen.

16) Das ist tatsächlich eine bescheuerte und schnell vergessene Eigenschaft. Vor allem deswegen, weil Binärzahlen selbst fehlen.

17) Es gibt eigentlich gar keinen speziellen Zeichentyp in C. Ein char ist nichts weiter als ein Typ für Zahlen mit einem sehr kleinen Definitionsbereich. Entsprechend kann man auch damit rechnen, z.B. char irgendwas='C'+23; oder großakleinadifferenz='A'-'a';
T$

Kommentare zu diesem Beitrag können per E-Mail an den Autor gesandt werden.

[ ← Zurück zur Übersicht ]

Impressum & Datenschutz