C im 21. Jahrhundert

Inhaltsverzeichnis
2.

C im 21. Jahrhundert

Ben Klemens

Deutsche Übersetzung von Thomas Demmig

Inhalt

Vorwort

C ist Punkrock

Fragen & Antworten (oder: Die Rahmenbedingungen für dieses Buch)

Standards: So viel Auswahl

Der POSIX-Standard

Ein bisschen Logistik

In diesem Buch genutzte Konventionen

Verwendung der Codebeispiele

Kontakt

Danksagungen

I. Die Umgebung

1. Richten Sie sich Ihre Umgebung ein

Einen Paketmanager einsetzen

C unter Windows kompilieren

POSIX für Windows

C mit POSIX kompilieren

C ohne POSIX kompilieren

Wo bitte geht es zur Bibliothek?

Ein paar meiner Lieblings-Flags

Pfade

Runtime-Linking

Makefiles verwenden

Variablen setzen

Die Regeln

Bibliotheken über ihren Quellcode nutzen

Bibliothek über ihren Quellcode nutzen – auch wenn Ihr Sysadmin das nicht will

C-Programme über Here-Dokumente kompilieren

Header-Dateien an der Befehlszeile einbinden

Der vereinheitlichte Header

Here-Dokumente

Von Stdin kompilieren

2. Debuggen, Testen, Dokumentieren

Einen Debugger verwenden

GDB-Variablen

Geben Sie Ihre Strukturen aus

Mit Valgrind auf Fehler prüfen

Unit-Tests

Ein Programm als Bibliothek verwenden

Abdeckung

Dokumentation einweben

Doxygen

Die Geschichte

Literaler Code mit CWEB

Fehlerprüfung

Wie ist der Anwender in den Fehler involviert?

Der Kontext, in dem der Anwender arbeitet

Wie sollte ein Hinweis auf einen Fehler zurückgegeben werden?

3. Verpacken Sie Ihr Projekt

Die Shell

Shell-Befehle durch ihre Ausgabe ersetzen

Die Shell für Schleifen nutzen, um auf einem Satz Dateien zu arbeiten

Dateien prüfen

fc

Makefiles vs. Shell-Skripten

Packen Sie Ihren Code mit den Autotools

Ein Autotools-Beispiel

Das Makefile durch Makefile.am beschreiben

Formvariablen

Inhaltsvariablen

Tests hinzufügen

Makefile-Elemente hinzufügen

Das configure-Skript

Weitere Shell-Elemente

4. Versionsverwaltung

Änderungen per diff

Git-Objekte

Der Stash

Bäume und ihre Zweige

Merging

Der Rebase

Remote-Repositories

5. Mit anderen zusammenspielen

Das Vorgehen

Schreiben, damit es von anderen Sprachen gelesen werden kann

Die Wrapper-Funktion

Datenstrukturen über die Grenze schmuggeln

Linken

Python als Host

Kompilieren und linken

Das bedingte Unterverzeichnis für Automake

Distutils mit Unterstützung durch die Autotools

II. Die Sprache

6. Ihr Weg zum Zeiger

Automatischer, statischer und manueller Speicher

Persistente Statusvariablen

Zeiger ohne malloc

Strukturen werden kopiert, Arrays werden als Alias weitergegeben

malloc und Speichertricks

Das Schicksal liegt in den Sternen

All die Zeigerarithmetik, die Sie kennen müssen

Typedef als lehrreiches Tool

7. C-Syntax, die Sie ignorieren können

Kümmern Sie sich nicht darum, explizit aus main zurückzukehren

Lassen Sie Deklarationen fließen

Die Array-Größe zur Laufzeit setzen

Weniger Casting

Enums und Strings

Labels, goto, switch und break

Durchdachtes goto

switch

Veraltetes Float

Vorzeichenlose Integerwerte vergleichen

8. Hindernisse und Gelegenheiten

Robuste und ansprechende Makros schreiben

Präprozessortricks

Mit static und extern verlinken

Extern verlinkte Variablen in Header-Dateien

Das Schlüsselwort const

Nomen-Adjektiv-Form

Spannungen

Tiefe

Das Problem mit char const **

9. Text

Den Umgang mit Strings mithilfe von asprintf einfacher gestalten

Sicherheit

Konstante Strings

Strings mit asprintf erweitern

Ein Loblied auf strtok

Unicode

Das Kodieren für C-Code

Unicode-Bibliotheken

Der Beispielcode

10. Bessere Strukturen

Compound-Literale

Initialisierung per Compound-Literal

Variadische Makros

Listen sicher abschließen

Mehrfache Listen

foreach

Eine Funktion vektorisieren

Designated Initializers

Arrays und Structs mit Nullen initialisieren

Typedefs retten Ihnen den Tag

Über Stil

Mehrere Elemente aus einer Funktion zurückgeben

Fehler melden

Flexible Eingabewerte für Funktionen

Deklarieren Sie Ihre Funktion im printf-Stil

Optionale und benannte Argumente

Eine alte Funktion aufpolieren

Der void-Zeiger und die Strukturen, auf die er zeigt

Funktionen mit generischen Eingabewerten

Generische Strukturen

11. Objektorientierte Programmierung in C

Was Sie nicht bekommen (und warum Sie es nicht vermissen werden)

Gültigkeitsbereich

Private Struct-Elemente

Überladen mit Operator-Überladung

_Generic

Strukturen und Dictionaries erweitern

Eine Struktur erweitern

C mit weniger Rissen

Ein Dictionary implementieren

Lassen Sie Ihren Code auf Zeigern auf Objekte basieren

Funktionen in Ihren Structs

Referenzen zählen

Beispiel: Ein Substring-Objekt

Ein agentenbasiertes Modell der Gruppenbildung

12. Bibliotheken

GLib

POSIX

Mit mmap riesige Datensätze verarbeiten

Einfaches Threading mit Pthreads

Die pthreads-Checkliste

Ressourcen in Threads mit Mutexen schützen

Das Beispiel

_Thread_local und statische Variablen

Die GNU Scientific Library

SQLite

Die Abfragen

libxml und cURL

Epilog

Glossar

Bibliografie

Stichwortverzeichnis

Über den Autor

Stichwortverzeichnis

Über den Übersetzer

Stichwortverzeichnis

Kolophon

Copyright

Vorwort

Is it really punk rock
Like the party line?

Wilco, »Too Far Apart«

C ist Punkrock

C besitzt nur eine Handvoll Schlüsselwörter, es hat seine Ecken und Kanten – und es rockt. Sie können alles mit ihm machen. Wie die C-, G- und D-Akkorde auf einer Gitarre können Sie die grundlegende Funktionsweise ziemlich schnell erlernen und dann den Rest Ihres Lebens damit verbringen, besser zu werden. Diejenigen, die das nicht schaffen, fürchten seine Macht und glauben, es sei zu unhandlich, um sicher damit umgehen zu können. Aber C ist immer noch bei Weitem die beliebteste unter den Sprachen, hinter denen keine Firma oder Stiftung mit viel Geld steht.[1]

Zudem ist die Sprache etwa 40 Jahre alt – also im besten Alter. Sie wurde von ein paar Leuten geschrieben, die im Grunde gegen das Management arbeiteten – eine perfekte Ausgangsbasis für Punkrock –, aber das war in den 1970ern, und seitdem hatte die Sprache ausreichend Zeit, den Mainstream zu erreichen.

Was taten die Leute, als der Punkrock im Mainstream ankam? In den Jahrzehnten seit seinem Auftauchen in den 1970ern ist der Punk sicherlich »normal« geworden: The Clash, The Offspring, Green Day und The Strokes haben weltweit Millionen von Alben verkauft (um nur ein paar zu nennen), und ich habe im Supermarkt harmlose Instrumentalversionen von Liedern gehört, die eigentlich mal Grunge waren. Der frühere Leadsänger von Sleater-Kinney hat nun eine beliebte Sketch-Comedy-Show, die regelmäßig Punkrocker veralbert.[2] Eine Reaktion auf die fortschreitende Evolution könnte die unnachgiebige Einstellung sein, nur das ursprüngliche Zeugs sei Punk und alles andere Easy-Punk-Pop für die Massen. Die Traditionalisten können immer noch ihre Alben aus den 70ern hören, und wenn die Platten abgenudelt sind, laden sie eine digital gemasterte Edition herunter. Für ihre Kinder können sie dann Ramones-Hoodies kaufen.

Die nicht Eingeweihten verstehen es einfach nicht. Manche von ihnen hören das Wort Punk und haben ein Bild aus dem 1970ern vor Augen – ein historisches Artefakt über ein paar Kids, die damals irgendwie alles etwas anders gemacht haben. Die traditionellen Punks, die immer noch ihre 1973er-Iggy-Pop-LP laufen lassen, erfreuen sich natürlich daran, aber sie untermauern die Annahme, Punk sei verknöchert und nicht mehr relevant.

Zurück in die Welt von C. Hier haben wir sowohl die Traditionalisten, die die Fahne von ANSI 89 hochhalten, als auch diejenigen, die einfach so schreiben, dass das Programm tut, was es soll, und die vielleicht nicht einmal bemerken, dass ihr Code sich in den 1990ern nicht hätte kompilieren lassen. Außenstehende verstehen den Unterschied nicht. Sie sehen Bücher aus den 1980ern, die immer noch nachgedruckt werden, und Onlinetutorials aus den 1990ern. Sie hören von Hardcore-Traditionalisten, die darauf bestehen, immer noch so wie damals zu schreiben, und sie wissen nicht, dass sich die Sprache und der Rest der Anwender weiterentwickelt haben. Das ist beschämend, da sie viele tolle Dinge verpassen.

Dies ist ein Buch über das Brechen von Traditionen und darüber, wie man dafür sorgt, dass C Punkrock bleibt. Ich interessiere mich nicht dafür, den Code aus diesem Buch mit der ursprünglichen C-Spezifikation aus Kernighans & Ritchies Buch von 1978 zu vergleichen. Mein Telefon besitzt 512 MByte Speicher – warum sollten unsere C-Lehrbücher noch Seiten darauf verwenden, Techniken zum Einsparen von Kilobytes in den Programmen zu beschreiben. Ich schreibe diesen Text auf einem einfachen Netbook, das 3,2 Milliarden Anweisungen pro Sekunde ausführen kann – warum soll ich mich darum scheren, ob bei einer Operation 8 oder 16 Bits verglichen werden müssen? Wir sollten Code schreiben, der sich schnell schreiben lässt und von unseren Kollegen gelesen werden kann. Wir schreiben weiterhin in C, daher wird unser lesbarer, aber nicht vollständig optimierter Code immer noch um Größenordnungen schneller laufen, als wenn wir vergleichbaren Code in einer der vielen anderen aufgeblasenen Sprachen schreiben würden.

Fragen & Antworten (oder: Die Rahmenbedingungen für dieses Buch)

F: Was unterscheidet dieses C-Buch von allen anderen?

A: Die Lehrbücher zu C ähneln sich alle sehr. (Ich habe sehr viele gelesen, unter anderem [Griffiths 2012], [Kernighan 1978, deutsch 1983], [Kernighan 1988, deutsch 1990], [Kochan 2004], [Oualline 1997], [Perry 1994], [Prata 2004] und [Ullman 2004].) Die meisten wurden geschrieben, bevor der C99-Standard viele Anwendungsaspekte vereinfacht hat, und bei manchen Büchern, die sich mittlerweile in der n-ten Auflage befinden, hat der Autor einfach nur ein paar Hinweise zu aktuellen Entwicklungen eingebaut, statt sich neue Gedanken über den Einsatz der Sprache zu machen. Sie erwähnen alle, dass es vielleicht Bibliotheken gibt, die Sie eventuell in Ihrem eigenen Code einsetzen können, aber diese Texte sind aus einer Zeit vor den aktuellen Installationstools und Ökosystemen, mit denen der Einsatz dieser Bibliotheken zuverlässig und ausreichend portabel wurde. Diese Lehrbücher sind immer noch korrekt und haben auch ihren Wert, aber moderner C-Code sieht einfach nicht mehr so aus wie der Code aus diesen Büchern.

Dieses Buch fängt da an, wo sie aufhören – es denkt neu über die Sprache und die Umgebung nach, in der sie eingesetzt wird. Es setzt einfach Bibliotheken für verkettete Listen und XML-Parser ein, statt alles von Grund auf selbst zu entwickeln. Das Buch dreht sich um das Schreiben von lesbarem Code und anwenderfreundlichen Funktionsschnittstellen.

F: Für wen ist dieses Buch gedacht? Muss ich ein Programmier-Guru sein?

A: Sie haben schon Programmiererfahrung in einer beliebigen Sprache, vielleicht in Java oder in einer Skriptsprache wie Perl. Ich muss Ihnen nicht mehr verkaufen, warum Ihr Code nicht nur aus einer langen Funktion ohne Unterfunktionen bestehen sollte.

Sie haben ein bisschen Wissen über C, aber machen Sie sich keine Sorgen, wenn Sie es nicht allzu gut kennen – wie ich noch erklären werde, gibt es eine ganze Menge Zeugs, das Sie besser nie erlernen sollten. Sind Sie in Bezug auf die C-Syntax noch völlig unbeleckt: Die Sprache ist fast aggressiv einfach, und die Suchmaschine Ihrer Wahl wird Sie zu Dutzenden von Onlinetutorials führen. Haben Sie schon Erfahrung mit anderen Sprachen, sollten Sie die Grundlagen in ein oder zwei Stunden draufhaben.

Ich möchte auch darauf hinweisen, dass ich mit Modeling with Data [Klemens 2008] ein Lehrbuch über statistisches und wissenschaftliches Programmieren geschrieben habe. Neben vielen Details zu numerischen Daten und statistischen Modellen für das Beschreiben von Daten gibt es hier ein eigenes Tutorial zu C, das natürlich meiner Meinung nach viele der Fehler älterer C-Tutorien vermeidet.

F: Ich bin Anwendungsentwickler, kein Kernel-Hacker. Warum sollte ich C nutzen, statt eine Sprache wie Python einzusetzen, mit der der Code schnell geschrieben ist?

A: Wenn Sie Anwendungsentwickler sind, ist dieses Buch für Sie genau richtig. Ich lese immer wieder, dass die Leute davon ausgehen, dass C eine Systemsprache ist. Aber das ist doch sehr brav gedacht – keiner kann uns sagen, was wir womit schreiben dürfen!

Aussagen wie »Unsere Sprache ist fast genauso schnell wie C, aber viel einfacher zu schreiben« sind so verbreitet, dass es sich fast schon um ein Klischee handelt. Klar, C ist auf jeden Fall so schnell wie C, und Ziel dieses Buchs ist, Ihnen zu zeigen, dass C sich viel einfacher einsetzen lässt, als die Lehrbücher aus den vergangenen Jahrzehnten vorgeben. Aufrufe von malloc und das Jonglieren mit der Speicherverwaltung sind nur noch halb so oft nötig wie in den 1990ern, der Umgang mit Strings lässt sich einfacher gestalten, und selbst die Syntax des Sprachkerns sorgt mittlerweile für mehr Lesbarkeit.

Ich habe tatsächlich mit C begonnen, weil ich eine Simulation beschleunigen musste, die in der Skriptsprache R lief. Wie so viele andere Skriptsprachen besitzt auch R eine C-Schnittstelle, über die die Anwender jederzeit ausweichen können, wenn die Hostsprache zu langsam ist. Schließlich hatte ich so viele Funktionen, die aus dem R-Skript in C-Code sprangen, dass ich die Hostsprache ganz aufgegeben habe. Und nun schreibe ich schließlich ein Buch über moderne C-Techniken.

F: Schön, dass Anwendungsentwickler, die von einer Skriptsprache kommen, dieses Buch mögen werden, aber ich bin ein Kernel-Hacker. Ich habe mir in der fünften Klasse C selbst beigebracht und habe sogar manchmal Träume, die sich korrekt kompilieren lassen. Was gibt es denn da noch Neues für mich?

A: C hat sich in den letzten 20 Jahren ziemlich weiterentwickelt. Wie ich später noch beschreiben werde, haben sich die Dinge, die garantiert von allen C-Compilern unterstützt werden, mit der Zeit geändert – dank der zwei neuen C-Standards, die seit dem ursprünglichen ANSI-Standard herausgekommen sind. Werfen Sie vielleicht einmal einen Blick in Kapitel 10 und schauen Sie, ob irgendwas Neues Sie dort überrascht.

Auch die Umgebung hat sich geändert. Die Autotools haben die gesamte Distribution von Code geändert, es ist jetzt viel einfacher, zuverlässig andere Bibliotheken aufzurufen. Das bedeutet, dass unser Code viel weniger Zeit damit verbringen sollte, gebräuchliche Strukturen und Routinen neu zu erfinden, und mehr Zeit damit, die Art von Bibliotheken aufzurufen, die in diesem Buch behandelt werden.

F: Mir ist aufgefallen, dass gut ein Drittel dieses Buchs fast keinen C-Code enthält.

A: Gute C-Praktiken erfordern gute C-Tools. Nutzen Sie keinen Debugger (eigenständig oder als Teil Ihrer IDE), machen Sie sich Ihr Leben viel schwerer. Wenn Sie mir erzählen wollen, es sei unmöglich, Speicherlecks zu finden, heißt das, Sie haben noch nicht von Valgrind gehört. Dabei handelt es sich um ein System, mit dem Sie auf die Codezeile genau angezeigt bekommen, wo Speicherlecks und Fehler entstehen. Python und Konsorten besitzen eingebaute Paketmanager – die plattformübergreifenden Paketmanager für C sind Stand-alone-Systeme mit ihrer eigenen Geschichte.

Nutzen Sie eine attraktive Integrated Development Environment (IDE) als Zentrale für all diese Tools, kann es trotzdem von Vorteil sein, wenn Sie wissen, wie Ihre IDE mit Umgebungsvariablen und anderen Details umgeht. Denn die werden zwar normalerweise vor Ihrem Auge verborgen, tauchen aber im Fehlerfall dann doch gern auf.

F: Manche der Tools, über die Sie schreiben, sind alt. Gibt es keine moderneren Alternativen für diese Shell-orientierten Programme?

A: Wenn wir uns über Leute lustig machen, die neue Dinge nur deshalb zurückweisen, weil sie neu sind, dürfen wir alten Dinge nicht gleichzeitig deshalb heruntermachen, weil sie alt sind.

Es ist recht zuverlässig ermittelt worden, dass die erste sechssaitige Gitarre um 1200, die erste viersaitige Geige um 1550 und das erste Klavier mit Tasten um 1700 gebaut wurden. Und es ist sehr wahrscheinlich, dass an den meisten Musikstücken, die Sie hören (wenn nicht gar an allen), eines dieser Instrumente beteiligt ist. Punkrock hat die Gitarre nicht abgelehnt, sondern stattdessen kreativ eingesetzt – zum Beispiel durch den Einsatz neuer Filter.

F: Ich habe Internet und kann Befehle und Syntaxdetails sofort nachschlagen. Warum sollte ich dieses Buch lesen?

A: Es stimmt, Sie können die Wertigkeit der Operatoren über die Befehlszeile eines Linux- oder Mac-Rechners mit man operator erhalten. Warum gehe ich hier noch mal drauf ein?

Ich habe das gleiche Internet wie Sie, und ich habe viel Zeit darin verbracht. Daher weiß ich auch recht gut, was Sie nicht im Internet finden – und das ist das, worüber ich in diesem Buch schreibe. Wenn ich ein neues Tool vorstelle, wie zum Beispiel gprof oder GDB, erfahren Sie bei mir genug, um loslegen zu können, um Ihre Suchmaschine mit sinnvollen Fragen zu füttern und um Dinge zu lernen, die in anderen Büchern nicht stehen (was eine Menge ist).

Standards: So viel Auswahl

Sofern nicht explizit erwähnt, ist alles in diesem Buch konform zu den Standards ISO C99 und C11. Um das ein bisschen zu erläutern und Ihnen ein wenig historisches Hintergrundwissen zu vermitteln, wollen wir die Liste der wichtigen C-Standards durchgehen (und dabei die kleineren Änderungen und Korrekturen ignorieren).

K & R (etwa 1978)

Dennis Ritchie, Ken Thompson und ein paar andere Leute entwickelten C, während sie das Betriebssystem Unix aufbauten. Brian Kernighan und Dennis Ritchie dokumentierten die Sprache schließlich in der ersten Auflage ihres Buchs, was zum ersten faktischen Standard wurde [deutsch Kernighan 1978].

ANSI C89

Die Bell Labs übergaben die Sprachverantwortung an das American National Standards Institute. 1989 veröffentlichte dieses seinen Standard, der ein paar Verbesserungen gegenüber K & R enthielt. Die zweite Auflage des Buchs von Kernighan und Ritchie enthielt eine vollständige Spezifikation der Sprache. Damit stand eine Kopie des ANSI-Standards auf dem Schreibtisch Zehntausender Programmierer [Kernighan 1988]. Der ANSI-Standard wurde von der International Organization for Standardization (ISO) ohne größere Änderungen 1990 übernommen, aber ANSI `89 scheint der gebräuchlichere Begriff zu sein (und macht sich auch besser auf einem T-Shirt).

Ein Jahrzehnt verging. C wurde Mainstream, das heißt, die Codegrundlage für so gut wie jeden PC und jeden Internetserver entstand in C. Das ist so viel Mainstream wie nur möglich.

In dieser Zeit spaltete sich C++ ab und kam groß raus (wenn auch nicht riesengroß). C++ war das Beste, was C je passieren konnte. Während jede andere Sprache zusätzliche Syntax nutzte, um dem objektorientierten Trend zu folgen (und all den anderen neuen Spielchen), blieb C bei seinem Standard. Diejenigen, die Stabilität und Portierbarkeit wollten, nutzten C, während die anderen, die mehr und mehr Features wünschten, um sich darin wälzen zu können, ihr C++ bekamen, und jeder war glücklich.

ISO C99

Ein Jahrzehnt später war der C-Standard gründlich überarbeitet worden. Es gab Ergänzungen für numerisches und wissenschaftliches Rechnen, dazu einen Standardtyp für komplexe Zahlen und ein paar typgenerische Funktionen. Einige Bequemlichkeiten aus C++ wurden übernommen, so zum Beispiel die einzeiligen Kommentare (die ursprünglich aus der C-Präprozessorsprache BCPL kamen) und die Möglichkeit, Variablen am Anfang von for-Schleifen zu definieren. Der Einsatz von Strukturen war dank einiger Ergänzungen zum Deklarieren und Initialisieren einfacher, dazu kamen wenige Syntaxverbesserungen. Die Dinge wurden modernisiert, um Sicherheitsüberlegungen Rechnung zu tragen und zu berücksichtigen, dass nicht jeder Englisch spricht.

Wenn Sie überlegen, wie viel Einfluss C89 hatte und wie viel C-Code rund um den Globus lief, wäre es ein Wunder gewesen, wenn die ISO keine Kritik hätte einstecken müssen. Und natürlich wurde der Standard kontrovers diskutiert. Es gibt zwei gebräuchliche Wege, eine komplexe Variable auszudrücken (durch rechteckige und Polarkoordinaten) – warum hat sich die ISO dann nur für einen entschieden? Warum brauchen wir einen Mechanismus für Makros mit variabler Anzahl an Parametern, wenn jeder gute Code ohne ihn auskommt? Mit anderen Worten – die Puristen beschuldigten die ISO, dem Druck nach mehr Features nachgegeben zu haben.

Aktuell unterstützen die meisten Compiler C99 plus/minus ein paar Kleinigkeiten. Der Typ long double scheint zum Beispiel viele Probleme zu verursachen. Allerdings gibt es eine bemerkenswerte Ausnahme: Microsoft weigert sich bisher, seinem Visual Studio C++-Compiler C99-Unterstützung angedeihen zu lassen. Der Abschnitt „C unter Windows kompilieren“ beschreibt ein paar der vielen Möglichkeiten, unter Windows C-Code zu kompilieren, daher ist es höchstens etwas unbequem, Visual Studio nicht einzusetzen. Und wenn jemand aus dem Establishment uns sagen will, dass wir kein ISO-Standard-C einsetzen können, macht es das erst recht zu Punkrock.

C11

Verunsichert wegen der Vorwürfe, sie würde die Sprache verraten, hat die ISO in der dritten Version des Standards nur wenige größere Änderungen vorgenommen. Wir haben jetzt eine Möglichkeit, typgenerische Funktionen zu schreiben, und es gibt weitere Verbesserungen in Bezug auf Sicherheit und den Einsatz von anderen Sprachen.

Ich schreibe dies im Jahr 2012, kurz nachdem der C11-Standard im Dezember 2011 erschien, und es gibt bereits etwas Unterstützung durch Compiler und Bibliotheken.

Der POSIX-Standard

So sieht es im Moment mit C selbst aus, aber die Sprache hat sich zusammen mit dem Betriebssystem Unix weiterentwickelt, und Sie werden im Buch immer wieder feststellen, dass sich diese Beziehung auch auf die tägliche Arbeit auswirkt. Wenn etwas an der Unix-Befehlszeile einfach zu erledigen ist, liegt das sehr wahrscheinlich daran, dass es in C einfach umzusetzen ist. Unix-Tools sind häufig entstanden, um das Schreiben von C-Code zu vereinfachen.

Unix

C und Unix wurden in den frühen 1970er-Jahren an den Bell Labs entworfen. Während des 20. Jahrhunderts stand Bell immer wieder im Zentrum von Monopol-Untersuchungen, daher gab es (unter anderem) eine Vereinbarung mit den US-Behörden, die festlegte, dass Bell im Softwarebereich nicht am Markt mitspielen würde. Unix wurde daher kostenlos an Forscher weitergegeben, die es auseinandernehmen und nachbauen konnten. Der Name Unix ist ein Markenzeichen, das ursprünglich den Bell Labs gehörte und in den Folgejahren von einer Firma zur nächsten wanderte.

Mit dem Analysieren, Reimplementieren und Verbessern des Codes durch viele Hacker entstanden Unix-Variationen. Es brauchte nur eine kleine Inkompatibilität, um ein Programm oder Skript nicht portieren zu können, daher zeigte sich schnell der Bedarf einer Standardisierung.

POSIX

Dieser Standard, der erstmals 1988 durch das Institute of Electrical and Electronics Engineers (IEEE) veröffentlicht wurde, bietet eine gemeinsame Basis für unixoide Betriebssysteme. Er legt fest, wie sich die Shell verhalten sollte, was von Befehlen wie ls und grep zu erwarten ist und welche C-Bibliotheken für C-Programmierer zur Verfügung zu stehen haben. So sind zum Beispiel die Pipes, die Befehlszeilenanwender nutzen, um Befehle zu verketten, hier im Detail definiert. Das bedeutet, dass die C-Funktion popen (Pipe Open) zum POSIX-Standard und nicht zum ISO-C-Standard gehört. Der POSIX-Standard wurde vielfach überarbeitet, die aktuelle Version ist POSIX:2008, die ich auch meine, wenn ich im Buch von »POSIX-Standard« spreche. Ein POSIX-konformes System muss einen C-Compiler besitzen, der über den Befehl c99 zu erreichen ist.

Dieses Buch nutzt diesen Standard, ich werde es aber auch entsprechend erwähnen.

Mit Ausnahme vieler Betriebssysteme von Microsoft baut so gut wie jedes andere Betriebssystem auf POSIX auf: Linux, Mac OS X, iOS, webOS, Solaris, BSD – selbst Windows-Server bieten ein POSIX-Subsystem an. Und für die Betriebssysteme, die nicht mitspielen wollen, zeige ich im Abschnitt „C unter Windows kompilieren“, wie Sie ein POSIX-Subsystem installieren.

Es gibt zwei POSIX-Implementierungen, auf die ich wegen ihrer Verbreitung und ihres Einflusses gesondert hinweisen möchte:

BSD

Nachdem Unix von den Bell Labs der Öffentlichkeit zur Verfügung gestellt wurde, um es analysieren zu können, haben Wissenschaftler an der University of California in Berkeley deutliche Verbesserungen daran vorgenommen und letztendlich die gesamte Codebasis von Unix neu geschrieben, um daraus die Berkeley Software Distribution zu erstellen. Nutzen Sie einen Computer von Apple, verwenden Sie BSD mit einer hübschen grafischen Oberfläche. BSD geht in vielen Fällen über POSIX hinaus, und wir werden noch über die eine oder andere Funktion sprechen, die zwar nicht zum POSIX-Standard gehört, aber zu nützlich ist, um sie zu ignorieren (vor allem das unentbehrliche asprintf).

GNU

Diese Abkürzung steht für GNU’s Not Unix, und GNU gehört zu der anderen großen Erfolgsgeschichte rund um das unabhängige Reimplementieren und Verbessern der Unix-Umgebung. Der Großteil der Linux-Distributionen greift sehr umfassend auf GNU-Tools zurück. Es ist ziemlich wahrscheinlich, dass Sie die GNU Compiler Collection (gcc) auf Ihrem POSIX-Rechner haben – selbst BSD nutzt sie. Auch hier definiert die gcc faktisch einen Standard, der C und POSIX an einigen Stellen erweitert. Ich werde es explizit erwähnen, wenn ich diese Erweiterungen einsetze.

Aus rechtlicher Sicht ist die BSD-Lizenz etwas großzügiger als die GNU-Lizenz. Da sich so mancher intensive Gedanken um die politischen und wirtschaftlichen Folgen dieser Lizenzen macht, gibt es sowohl GNU- als auch BSD-Versionen der meisten Tools. So sind zum Beispiel sowohl die GNU Compiler Collection (gcc) als auch clang von BSD führende C-Compiler. Die Autoren beider Tools schauen regelmäßig, was die jeweils anderen machen, und orientieren sich daran. Wir können daher davon ausgehen, dass die Unterschiede mit der Zeit immer kleiner werden.

Ein bisschen Logistik

In diesem Buch genutzte Konventionen

Die folgenden typografischen Konventionen werden in diesem Buch verwendet:

Kursiv

Steht für neue Begriffe, Dateinamen und Pfade, URLs und E-Mail-Adressen. Viele neue Begriffe sind in einem Glossar am Ende des Buchs definiert.

Nichtproportionalschrift

Wird für Programmlistings genutzt, aber auch für Code innerhalb eines Absatzes, und bezieht sich auf Programmelemente wie Variablen- oder Funktionsnamen, Datenbanken, Datentypen, Umgebungsvariablen, Anweisungen und Schlüsselwörter.

Nichtproportionalschrift kursiv

Steht für Text, der durch vom Anwender bereitgestellte oder durch den Kontext ermittelbare Werte ersetzt werden soll.

Tipp

Dieses Symbol weist auf einen Tipp, einen Vorschlag oder eine allgemeine Anmerkung hin.

Anmerkung

Sie sind dran: Dies sind Übungen, durch die Sie lernen, indem Sie sich selbst mal wieder an die Tastatur setzen.

Achtung

Dieses Symbol weist auf eine Warnung hin.

Verwendung der Codebeispiele

Dieses Buch ist dazu gedacht, Ihnen bei der Erledigung Ihrer Arbeit zu helfen. Im Allgemeinen dürfen Sie den Code in diesem Buch in Ihren eigenen Programmen oder Dokumentationen verwenden. Solange Sie den Code nicht in großem Umfang reproduzieren, brauchen Sie uns nicht um Erlaubnis zu bitten. Zum Beispiel benötigen Sie nicht unsere Erlaubnis, wenn Sie ein Programm unter Zuhilfenahme mehrerer Codestücke aus diesem Buch schreiben. Wenn Sie allerdings einen Datenträger mit Beispielen aus O'Reilly-Büchern verkaufen oder vertreiben wollten, müssen Sie eine Genehmigung von uns einholen. Eine Frage mit einem Zitat oder einem Codebeispiel aus dem Buch zu beantworten, erfordert keine Genehmigung. Signifikante Teile von Beispielcode aus dem Buch für die eigene Produktdokumentation zu verwerten, ist dagegen genehmigungspflichtig.

Wir freuen uns über eine Quellenangabe, verlangen sie aber nicht unbedingt. Zu einer Quellenangabe gehören normalerweise Autor, Titel, Verlagsangabe, Veröffentlichungsjahr und ISBN, hier also: »Ben Klemens, C im 21. Jahrhundert, 2. Auflage, O’Reilly Verlag 2014, ISBN 978-3-95561-692-2«.

Sollten Sie das Gefühl haben, Ihre Verwendung der Codebeispiele könnte gegen das Fairnessprinzip oder die Genehmigungspflicht verstoßen, dann nehmen Sie bitte unter Kontakt mit uns auf.

Kontakt

Bitte richten Sie Anfragen und Kommentare zu diesem Buch an den Verlag:

O’Reilly Verlag GmbH & Co. KG
Balthasarstraße 81
50670 Köln
Tel.: +49(0)221-973160-0
Fax: +49(0)221-973160-8

Wir haben eine Webseite zu diesem Buch eingerichtet, auf der Errata, die Codebeispiele und zusätzliche Informationen veröffentlicht werden. Sie finden die Seite unter:

http://www.oreilly.de/catalog/21stcenturyc2ger/

Kommentare oder technische Fragen zu diesem Buch schicken Sie bitte per E-Mail an:

Weitere Informationen zum gesamten Angebot des O'Reilly Verlags finden Sie auf unserer Website: http://www.oreilly.de.

Wir sind auf Facebook: facebook.com/oreilly.de

Folgen Sie uns auf Twitter: twitter.com/OReilly_Verlag/

Unsere Google+-Seite: http://bit.ly/googleplus_oreillyverlag

Danksagungen

Nora Albert: allgemeine Unterstützung, Meerschweinchen
Bruce Fields, Dave Kitabjian, Sarah Weissman: umfassende und gründliche Durchsicht
Patrick Hall: Unicode-Wissen
Nathan Jepson und Shawn Wallace: Lektorat
Rolando Rodríguez: Testen, erforschen und entdecken
Rachel Steely: Produktion
Ulrik Sverdrup: für den Hinweis, dass wir wiederholte Designated Initializer nutzen können, um Standardwerte zu setzen


[1] Dieses Vorwort verneigt sich (ziemlich offensichtlich) vor »Punk Rock Languages: A Polemic« von Chris Adamson (siehe http://pragprog.com/magazines/2011-03/punk-rock-languages).

[2] War Sleater-Kinney mit Texten wie »Can’t get to heaven with a three-chord song« vielleicht Post-Punk? Leider gibt es keinen ISO-Punk-Standard, mit dem wir exakt ermitteln können, was noch dazugehört und was nicht.

Teil I. Die Umgebung

In der Wildnis – da, wo es die eingezäunten Gärten der Skriptsprachen nicht gibt – finden sich viele Tools, mit denen sich die großen Ärgernisse von C beseitigen lassen. Aber Sie müssen sie erst finden. Und ich meine wirklich müssen: Viele dieser Tools sind unabdingbar, um schmerzfrei programmieren zu können. Nutzen Sie keinen Debugger (Stand-alone oder innerhalb einer IDE), ist das eine Form von Selbstkasteiung.

Es gibt unglaublich viele Bibliotheken, die nur darauf warten, von Ihnen eingesetzt zu werden. So können Sie sich mit Ihrem eigentlichen Problem befassen und müssen keine Zeit damit verschwenden, verkettete Listen, Parser und andere Grundlagen noch einmal zu implementieren. Es muss für Sie so einfach wie möglich sein, Ihr Programm mit externen Bibliotheken kompilieren zu können.

Dies ist ein Überblick über Teil I:

Kapitel 1 behandelt die grundlegende Umgebung, einschließlich des Beschaffens eines Paketmanagers und des Installierens aller erforderlichen Tools. Das ist die Basis für den interessanteren Teil, bei dem wir Programme mit Bibliotheken aus allen möglichen Quellen kompilieren. Der Prozess ist recht standardisiert, und es gehört ein kleiner Satz an Umgebungsvariablen und Rezepten dazu.

Kapitel 2 stellt Tools für das Debuggen, Dokumentieren und Testen vor, denn wie gut ist Code, wenn er nicht debuggt, dokumentiert und getestet wurde?

Kapitel 3 behandelt die Autotools, ein System für das Zusammenstellen Ihres Codes zur Distribution. Das Kapitel ist aber etwas ausführlicher und kümmert sich auch um das Schreiben von Shell-Skripten und Makefiles.

Nichts macht das Leben komplizierter als andere Personen. Daher kümmert sich Kapitel 4 um Git, ein System zum Verfolgen all der leicht unterschiedlichen Versionen eines Projekts, die sich auf Ihrer Festplatte und denen Ihrer Kollegen befinden, und zum einfachen Zusammenführen all dieser Versionen.

Andere Sprachen sind ein wichtiger Teil moderner C-Umgebungen, da so viele Sprachen eine C-Schnittstelle anbieten. Kapitel 5 gibt einige allgemeine Hinweise zum Schreiben der Schnittstelle und enthält ein umfangreicheres Beispiel mit Python.