C (Programmiersprache)

aus Wikipedia, der freien Enzyklopädie
Wechseln zu: Navigation, Suche
C
Paradigmen: imperativ, strukturiert
Erscheinungsjahr: 1972
Entwickler: Dennis Ritchie & Bell Labs
Wichtige Implementierungen: GCC, MSVC, Borland C, Portland Group, Intel, Clang
Beeinflusst von: B, BCPL, ALGOL 68,[1]
Beeinflusste: awk, C++, C#, Objective-C, D, Go, Java, JavaScript, PHP, Perl

C ist eine imperative Programmiersprache, die der Informatiker Dennis Ritchie[1] in den frühen 1970er Jahren an den Bell Laboratories für die Systemprogrammierung des Betriebssystems Unix entwickelte. Seitdem ist sie auf vielen Computersystemen verbreitet.

Die Anwendungsbereiche von C sind sehr verschieden. Sie wird zur System- und Anwendungsprogrammierung eingesetzt. Die grundlegenden Programme aller Unix-Systeme und die Systemkernel vieler Betriebssysteme sind in C programmiert. Zahlreiche Sprachen, wie C++, Objective-C, C#, D, Java, JavaScript, PHP, Vala oder Perl orientieren sich an der Syntax und anderen Eigenschaften von C.

Überblick[Bearbeiten]

C ist eine Programmiersprache, die auf fast allen Computersystemen zur Verfügung steht. Sie zählt zu den sogenannten prozeduralen Programmiersprachen. Um den Wildwuchs zahlreicher Dialekte einzudämmen, wurde C mehrfach standardisiert (C89/C90, C95, C99, C11). Abgesehen vom Mikrocontrollerbereich, wo eigene Dialekte existieren, sind die meisten aktuellen PC-/Server-Implementierungen eng an den Standard angelehnt; eine vollständige Implementierung aktueller Standards ist aber selten. In den meisten C-Systemen mit Laufzeitumgebung steht auch die genormte C-Standard-Bibliothek zur Verfügung. Dadurch können C-Programme, die keine sehr hardware-nahe Programmierung enthalten, in der Regel gut auf andere Zielsysteme portiert werden. Konzeptionell ist C auf einfache Kompilierbarkeit ausgelegt. Die Compiler erzeugen in der Regel aber auch nur wenig Code zur Gewährleistung der Sicherheit zur Laufzeit der Programme.

Die Verbreitung von C ist groß, und viele Programmierschnittstellen für Anwendungsprogramme und Betriebssystem-APIs werden in Form von C-Schnittstellen implementiert, z. B. Win32.[2]

Geschichte[Bearbeiten]

Frühe Entwicklungen[Bearbeiten]

C wurde 1969–1973 von Dennis Ritchie[1] in den Bell Laboratories für die Programmierung des damals neuen UNIX-Betriebssystems entwickelt. Er stützte sich dabei auf die Programmiersprache B, die Ken Thompson und Dennis Ritchie in den Jahren 1969/70 geschrieben hatten – der Name C entstand als Weiterentwicklung von B. B wiederum geht auf die von Martin Richards Mitte der 1960er-Jahre entwickelte Programmiersprache BCPL zurück.[3] Ritchie schrieb auch den ersten Compiler für C. 1973 war die Sprache so weit ausgereift, dass man nun den Unix-Kernel für den PDP-11 neu in C schreiben konnte.

K&R C[Bearbeiten]

1978 veröffentlichten Brian W. Kernighan und Dennis Ritchie die erste Auflage von The C Programming Language (deutsch: Programmieren in C). Die darin beschriebene Fassung von C, die nach den Buchautoren „K&R C“ genannt wird, erweiterte die ursprüngliche Sprache um neue Schlüsselwörter wie long int oder unsigned int und führte erstmals die I/O-Standardbibliothek ein. Bis zur Standardisierung der Sprache diente die von Kernighan und Ritchie geschriebene Spezifikation als informelle Referenz für das Programmieren in C.

Normen und Standards[Bearbeiten]

→ Hauptartikel: Varianten der Programmiersprache C

C verbreitete sich rasch und wurde laufend weiterentwickelt. Das führte dazu, dass das von Kernighan und Ritchie beschriebene C nicht mehr dem C entsprach, das von den Compilern unterstützt wurde. Um eine Normierung der Sprache zu erreichen, setzte das American National Standards Institute (ANSI) 1983 ein Komitee namens X3J11 ein, das 1989 schließlich die Norm ANSI X3.159-1989 Programming Language C verabschiedete. Ein Jahr später übernahm die ISO diese Norm (mit kleinen Änderungen) als C90. 1995 veröffentlichte die ISO eine Ergänzung zur Norm (C95). 1999 wurde der Standard ISO/IEC 9899 verabschiedet. Mit diesem Standard, der als C99 bekannt ist, flossen auch aus C++ bekannte Erweiterungen zurück in die Sprache C. Danach arbeitete das Normierungskomitee WG14 an der nächsten Erweiterung der Programmiersprache unter dem Arbeitstitel C1X , die am 8. Dezember 2011 als C11 veröffentlicht wurde.[4][5]

Verwendung[Bearbeiten]

Das Haupteinsatzgebiet von C liegt in der Systemprogrammierung einschließlich der Erstellung von Betriebssystemen und der Programmierung von eingebetteten Systemen. Der Grund liegt in der Kombination von erwünschten Charakteristiken wie Portabilität und Effizienz mit der Möglichkeit, Hardware direkt anzusprechen und dabei niedrige Anforderungen an die Laufzeitumgebung zu haben.

Auch Anwendungssoftware wird oft in C erstellt.

Wegen der hohen Ausführungsgeschwindigkeit und geringen Codegröße werden Compiler, Programmbibliotheken und Interpreter anderer höherer Programmiersprachen (wie z. B. die Java Virtual Machine) oft in C implementiert.

C wird als Zwischencode einiger Implementierungen höherer Programmiersprachen verwendet. Dabei wird diese zuerst in C-Code übersetzt, der dann kompiliert wird. Dieser Ansatz wird entweder verwendet, um die Portabilität zu erhöhen (C-Compiler existieren für nahezu jede Plattform), oder aus Bequemlichkeit, da kein maschinenspezifischer Codegenerator entwickelt werden muss. Einige Compiler, die C auf diese Art benutzen, sind Chicken, EiffelStudio, Esterel, PyPy, Sather, Squeak und Vala.

C wurde allerdings als Programmiersprache und nicht als Zielsprache für Compiler entworfen. Als Zwischensprache ist es daher eher schlecht geeignet. Das führte zu C-basierten Zwischensprachen wie C--.

C wird oft für die Erstellung von Anbindungen genutzt (zum Beispiel Java Native Interface). Diese Anbindungen erlauben es Programmen, die in einer anderen Hochsprache geschrieben sind, Funktionen aufzurufen, die in C implementiert wurden. Der umgekehrte Weg ist oft ebenfalls möglich und kann verwendet werden, um in C geschriebene Programme mit einer anderen Sprache zu erweitern (z. B. mod perl).

Eigenschaften[Bearbeiten]

  • C gehört zu den imperativen Programmiersprachen.
  • C besitzt eine sehr kleine Menge an Schlüsselwörtern. Die Anzahl der Schlüsselwörter ist so gering, weil fast alle Aufgaben, welche in anderen Sprachen über eigene Schlüsselwörter realisiert werden, über einzubindende Bibliotheksroutinen realisiert werden (zum Beispiel die Ein-/Ausgabe über Konsole oder auf Dateien, die dynamische Speicherverwaltung, ...) oder über spezielle syntaktische Konstrukte (zum Beispiel Variablendeklarationen). („C kann ohne Bibliotheken fast gar nichts.“) Daraus ergibt sich der Vorteil eines sehr einfachen, kleinen Compilers: Auf neuen Computersystemen ist C oft die erste verfügbare Programmiersprache (nach Maschinencode und Assembler).
  • C ermöglicht direkte Speicherzugriffe und sehr hardwarenahe Konstrukte. Es eignet sich daher gut zur Systemprogrammierung. Sollen Programme portierbar sein, sollte von diesen Möglichkeiten aber möglichst wenig Gebrauch gemacht werden.
  • C schränkt direkte Speicherzugriffe kaum ein. Dadurch kann der Compiler (anders als zum Beispiel in Pascal) nur sehr eingeschränkt bei der Fehlersuche helfen. Aus diesem Grund ist C für sicherheitskritische Anwendungen (Medizintechnik, Verkehrsleittechnik, Raumfahrt) weniger geeignet.
  • C enthält einige sicherheitskritische Funktionen; so überschreibt zum Beispiel gets(), eine Funktion der Standardbibliothek, fremde Speicherbereiche (Pufferüberlauf), wenn es auf eine unpassende (zu lange) Eingabe stößt. Der Fehler ist innerhalb von C weder bemerk- noch abfangbar. Um den großen Vorteil von C – die Existenz zahlreicher älterer Quellcodes – nicht zu verlieren, unterstützen auch aktuelle Implementierungen weiterhin diese und ähnliche Funktionen, warnen jedoch in der Regel, wenn sie beim Übersetzen im Quelltext benutzt werden.
  • C ist nicht typsicher[6], da völlig verschiedene Datentypen zuweisungskompatibel gehandhabt werden können.[7]
  • Historisch bedingt existieren in C keine Funktionen zur positionierten Ausgabe. Es existieren jedoch zahlreiche Bibliotheken, die für das jeweilige Zielsystem eine solche Ausgabe ermöglichen.
  • In den C-Standard-Bibliotheken gibt es keine grafische Ein-/Ausgabe.
  • C verwendet im Quellcode einige Sonderzeichen (z. B. „{“, „|“ und „&“), die in der Vergangenheit nicht auf allen Zielsystemen zur Verfügung standen. Das hat dazu geführt, dass C sich auf jenen Systemen nicht verbreiten konnte. C bietet zwar eine Alternativschreibweise über Trigraphen, was jedoch die Lesbarkeit des Quelltextes enorm verschlechtert.
  • Eine Modularisierung in C erfolgt auf Dateiebene. Eine Datei bildet eine Übersetzungseinheit; intern benötigte Funktionen und Variablen können so vor anderen Dateien verborgen werden. Die Bekanntgabe der öffentlichen Funktionsschnittstellen erfolgt mit so genannten Header-Dateien. Damit verfügt C über ein schwach ausgeprägtes Modulkonzept.[8][9]

Die Programmiersprache C wurde mit dem Ziel entwickelt, eine echte Sprachabstraktion zur Assemblersprache zu implementieren. Es sollte eine direkte Zuordnung zu wenigen Maschineninstruktionen geben, um die Abhängigkeit von einer Laufzeitumgebung zu minimieren. Als Resultat dieses Designs ist es möglich, C-Code auf einer sehr hardwarenahen Ebene zu schreiben, analog zu Assemblerbefehlen. Die Portierung eines C-Compilers auf eine neue Prozessorplattform ist, verglichen mit anderen Sprachen, wenig aufwändig. Bspw. ist der freie GNU-C-Compiler (gcc) für eine Vielzahl unterschiedlicher Prozessoren und Betriebssysteme verfügbar. Für den Entwickler bedeutet das, dass unabhängig von der Zielplattform fast immer auch ein C-Compiler existiert. C unterstützt damit wesentlich die Portierbarkeit von Programmen, sofern der Programmierer auf Assemblerteile im Quelltext und/oder hardwarespezifische C-Konstrukte verzichten kann. In der Mikrocontroller-Programmierung ist C die mit Abstand am häufigsten verwendete Hochsprache.

Datentypen[Bearbeiten]

Jeder Ausdruck und Bezeichner in C hat einen bestimmten Datentyp. C unterscheidet zwischen:

  • Objekttypen (object types)
  • Funktionstypen (function types)
  • unvollständige Typen (incomplete types)

Außerdem wird zwischen Basisdatentypen (basic types) und abgeleiteten Typen (derived types) unterschieden.

Basisdatentypen[Bearbeiten]

C verfügt über 19 Basisdatentypen (eng. basic types). Diese werden in Datentypen für Ganzzahl- und Gleitkommazahlen aufgeteilt. Die verschiedenen Typen ermöglichen bei unterschiedlichem Speicherbedarf das Speichern von Daten aus einem unterschiedlich großen maximalen Wertebereich.

  • void ist der leere Datentyp. Er kann keine Werte aufnehmen. void ist ein unvollständiger Typ, darum können keine Variablen von diesem Typ deklariert werden. Ein Rückgabetyp void bedeutet, dass die Funktion keinen Wert zurückgibt. Eine Variable vom Typ void * zeigt auf Objekte mit unspezifiziertem Typ.
  • _Bool dient zur Repräsentation von Wahrheitswerten. Er existiert als eigener Datentyp seit C99 und kann nur die Werte 0 und 1 aufnehmen. Die Größe eines _Bools ist plattformabhängig und kann größer als ein char sein.
  • char und wchar_t dienen zur Speicherung alphanumerischer Daten. Sie werden in C als Ganzzahl-Datentypen (mit besonderen Eigenschaften) behandelt. Außerdem repräsentiert ein char die kleinste adressierbare Einheit in C. Die Größe von Objekten und Typen wird stets als ganzzahliges Vielfaches eines char angegeben.
  • int ist der Standarddatentyp für ganzzahlige Werte. Für eventuell größere oder kleinere Wertebereiche existieren die Typen char, short int, long int und (seit C99) long long int.[2][10][11] Der Verzicht auf festgeschriebene Größen und Wertebereiche, um möglichst viele Architekturen zu unterstützen, wird durch definierte minimale Wertebereiche und die folgende feste Relation abgemildert:
signed charshort intintlong intlong long int.
(„≤“ bedeutet dabei, dass der rechts stehende Typ alle Werte des links stehenden Typs aufnehmen kann.)
Alle int-Typen sind vorzeichenbehaftet (±), die entsprechende Kennzeichnung durch ein vorangestelltes signed kann weggelassen werden. Es existiert jedoch zu jedem Typ ein zugehöriger vorzeichenloser Typ (nur positive Ganzzahlen und 0), der durch ein vorangestelltes unsigned bestimmt wird. Er benötigt den gleichen Speicherplatz wie sein entsprechender vorzeichenbehafteter Typ.
Das Schlüsselwort int kann bei den mehrteiligen Typnamen weggelassen werden (long, long long).
Der Typ char muss nicht mit signed char übereinstimmen, sondern kann ein zu unsigned char identisches Bit-Layout und identische Rechenregeln besitzen – dies kann je nach Plattform verschieden sein.
Für jeden Typ schreibt der Standard eine Mindestgröße vor; In einer Implementierung können die Werte auch größer sein. Die tatsächliche Größe eines Typs ist in der Headerdatei <limits.h> abgelegt. INT_MAX ersetzt der C-Präprozessor beispielsweise durch den Wert, den der Typ int maximal annehmen kann.[12]
  • float, double und long double sind die drei Datentypen für Gleitkommazahlen. Auf den meisten Architekturen entsprechen float und double den IEEE-Datentypen. Welchen Wertebereich ein Gleitkommazahltyp auf einer Implementierung einnimmt, ist ebenfalls plattformabhängig; der Standard legt nur wieder fest, dass der Wertebereich von float nach double und von double nach long double jeweils entweder gleich bleibt oder zunimmt. Die genauen Eigenschaften und Wertebereiche auf der benutzten Architektur können über die Headerdatei <float.h> ermittelt werden.[13]

Die C-Standard-Bibliothek ergänzt diese Datentypen über die plattformunabhängige Header-Datei stdint.h in der ein Set von Ganzzahltypen mit fester Länge definiert ist.

Komplexe Zahlen[Bearbeiten]

Zusätzlich existieren seit C99 noch drei Gleitkomma-Datentypen für komplexe Zahlen, welche aus den drei Gleitkommatypen abgeleitet sind: float _Complex, double _Complex und long double _Complex. Ebenfalls in C99 eingeführt wurden Gleitkomma-Datentypen für rein imaginäre Zahlen: float _Imaginary, double _Imaginary und long double _Imaginary.

In einer hosted-Umgebung müssen die _Complex-Datentypen vorhanden sein; die _Imaginary-Typen sind optional. In einer freestanding-Umgebung sind alle diese sechs Datentypen optional.[14]

Abgeleitete Typen[Bearbeiten]

Aus den Basisdatentypen und bereits deklarierten abgeleiteten Typen lassen sich beliebig viele weitere Typen ableiten. Abgeleitete Typen werden wie folgt aufgeteilt:

Felder (array types)
Zu jedem Typ T existieren Feldtypen der Art „Feld von n Elementen vom Typ T“, die dann T[n] geschrieben werden.
Zeiger (pointer types)
Zu jedem Typ T existiert ein Typ „Zeiger auf T“, der T * geschrieben wird.
Funktionen (function types)
Zu jedem Typ T existieren Typen „Funktion, die ein T zurückgibt“. Dies wird durch Anhängen von () gekennzeichnet, wobei in die Klammern ggf. noch die Typen der Funktionsparameter geschrieben werden.
zusammengesetzte Typen (structure types und union types)
Hierbei werden mehrere Objekte zu einem neuen Typ zusammengefasst.

Es ist möglich und üblich, von abgeleiteten Typen weitere Ableitungen zu definieren:

int array[10][20];  // Array mit 10 Elementen, wobei jedes Element ein Array von 20 »int« ist.
int  *p [10];       // Array mit 10 Elementen, wobei jedes Element ein »int *« (=Zeiger auf »int«) ist.
int (*q)[10];       // Zeiger auf ein Array mit 10 »int«-Elementen.
int (*f)(int *);     // Zeiger auf eine Funktion, die einen »int *«-Parameter hat und ein »int« zurückgibt

Dies kann schnell zu komplexen und unübersichtlichen Deklarationen führen. Über eine typedef-Deklaration ist es möglich, für einen (möglicherweise zu komplexen) Datentyp einen einfachen Namen zu vergeben:

void *(*get_cb(int))(void *);       // Unübersichtlich!
 
// Besser:
typedef void *(*callback)(void *); // Typedef:  »callback« ist ein Zeiger auf eine Funktion,
                                   // die einen »void*«-Parameter hat und ein »void*« zurückgibt
callback get_cb(int);              // Übersichtlicher: »get_cb« hat einen »int«-Parameter und gibt einen
                                   // »callback«-Funktionszeiger zurück

Datenmodell[Bearbeiten]

Die C-Sprachnorm legt die Größe (und damit den Wertebereich) der einzelnen Basisdatentypen nicht fest, sondern definiert lediglich Relationen zwischen den Größen der Basisdatentypen und fordert für jeden Basisdatentyp jeweils Mindestgrößen. Daraus ergeben sich in der Praxis mehrere Ausgestaltungsmöglichkeiten, welche man Datenmodell oder auch Programmiermodell nennt.

Der Datentyp int wird auf einer Plattform in der Regel so festgelegt, dass seine Größe der natürlichen Datenwortgröße der CPU entspricht. Die Größe der Zeigertypen richtet sich nach der Größe des Speicherbereichs, der vom Programm aus adressierbar sein soll. Dieser Speicherbereich kann kleiner, aber auch größer sein, als der von der CPU-Architektur adressierbare Speicherbereich.

Auf heutigen Architekturen ist ein char meist 8 Bit groß, die anderen Datentypen müssen somit ein ganzzahliges Vielfaches von 8 Bit groß sein. Damit ergeben sich folgende mögliche Datenmodelle:

Bits pro Datentyp
Datenmodell Datentyp Plattformen (Auswahl)
char short int long long long void*
IP16 8 16 16 32 64 16 MS DOS im SMALL memory model
LP32 8 16 16 32 64 32 MS DOS im LARGE memory model
ILP32 8 16 32 32 64 32 die meisten 32-Bit-Betriebssysteme
LLP64 8 16 32 32 64 64 Windows auf x86-64 und IA64
LP64 8 16 32 64 64 64 die meisten unixoiden Betriebssysteme auf 64-Bit-Plattformen
ILP64 8 16 64 64 64 64 SPARC64
SILP64 8 64 64 64 64 64 Unicos (Cray)

Deklarationen[Bearbeiten]

Bevor Variablen, Typen und Funktionen in C verwendet werden können, müssen sie deklariert werden (sog. Statische Typisierung). Eine so deklarierte Variable, Typ oder Funktion erhält einen Namen (Bezeichner, engl. identifier). Die Vergabe von Bezeichnern ist an bestimmte Regeln gebunden:

  • Das erste Zeichen eines Bezeichners muss ein Buchstabe oder Unterstrich sein.
  • Die folgenden Zeichen dürfen nur die Buchstaben A–Z und a–z, Ziffern und der Unterstrich sein.
  • Ein Bezeichner darf kein Schlüsselwort der Sprache – zum Beispiel if, void und auto – sein.

Seit C95 sind auch Zeichen aus dem Universal Character Set in Bezeichnern erlaubt, sofern die Implementierung es unterstützt. Die erlaubten Zeichen sind in Anhang D des ISO-C-Standards aufgelistet. Vereinfacht gesagt, sind es all jene Zeichen, die in irgendeiner Sprache als Buchstabe oder buchstabenähnliches Zeichen Verwendung finden. Im Quelltext lassen sich diese Zeichen plattformunabhängig über eine Escape-Sequenz wie folgt ersetzen:

  • \uXXXX (wobei X für eine Hexadezimalziffer steht) für Zeichen mit einem Code von 00A0hex bis FFFFhex.
  • \UXXXXXXXX für alle Zeichen mit einem Code ≥00A0hex.

Das folgende Beispiel deklariert und definiert die Namen variable_1 und variable_2 als Variablen vom Typ Integer:

void beispiel1()
{
  int variable_1, variable_2;
}

Bestimmte Bezeichner sind außerdem für die Implementierung reserviert:

  • Bezeichner, die mit zwei aufeinanderfolgenden Unterstrichen beginnen
  • Bezeichner, die mit Unterstrich gefolgt von einem Großbuchstaben anfangen.

Erweiterungen am Sprachkern, die neue Schlüsselwörter erfordern, verwenden dafür ebenfalls Namen aus diesem reservierten Bereich, um zu vermeiden, dass sie mit Bezeichnern in existierenden C-Programmen kollidieren, z. B. __attribute__, _Complex, _Generic, _Thread_local.

Aufbau eines Programms in C[Bearbeiten]

Das globale Sprachdesign sieht vor, dass ein Programm aus mehreren Modulen bestehen kann. Für jedes Modul existiert eine Quellcode-Datei (mit der Endung .c) und eine Header-Datei (mit der Endung .h). Die Quellcode-Datei enthält im Wesentlichen die Implementierung, die Header-Datei das Interface nach außen. Beide Dateien konsistent zu halten, ist bei C (wie auch bei C++) Aufgabe des Programmierers.

Module, die Funktionen aus anderen Modulen benutzen, inkludieren deren Header-Dateien und geben dem Compiler damit die notwendigen Informationen über die vorhandenen Funktionen, Aufrufkonventionen, Typen und Konstanten.

Jedes Modul kann für sich übersetzt werden und erzeugt eine Object-Datei. Mehrere Object-Dateien können zu einer Bibliothek zusammengefasst werden oder einzeln verwendet werden.

Mehrere Object-Dateien sowie Bibliotheken (die auch nur eine Sammlung von Objekt-Dateien sind) können mittels Linker (deutsch: Binder) zu einem ausführbaren Programm gebunden werden.

Beispielprogramm in C[Bearbeiten]

Der folgende Quelltext stellt ein einfaches C-Programm dar, das die Textzeile Hallo Welt!, gefolgt von einem Zeilenumbruch, ausgibt. Dieses Beispiel folgt den Vorgaben des ANSI-C-Standards; andere Versionen dieses Programms sind im Artikel Liste von Hallo-Welt-Programmen/Programmiersprachen beschrieben.

#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    puts("Hallo Welt!");
    return EXIT_SUCCESS;
} /* end main() */

In der ersten Zeile ermöglicht die Präprozessordirektive #include <stdio.h> die spätere Verwendung von Funktionen aus der Ein-/Ausgabe-Bibliothek stdio (auch „standard-input/output“ genannt). Diese include-Anweisung veranlasst den C-Präprozessor, vor der Übersetzung die Headerdatei stdio.h in den Quelltext zu kopieren, die unter anderem eine Deklaration der weiter unten verwendeten Ausgabefunktion puts enthält. In der zweiten Zeile wird die Headerdatei stdlib.h eingebunden, die die symbolische Konstante EXIT_SUCCESS definiert, damit die erfolgreiche Programmausführung dem Aufrufer plattformunabhängig signalisiert werden kann (siehe Zeile 7 des Programms). Include-Anweisungen können zwar an jeder Stelle im Quelltext eingefügt werden, meist werden sie jedoch an den Anfang eines Programmtextes gestellt, um die Übersichtlichkeit zu erhöhen.

In der vierten Zeile beginnt das eigentliche Programm mit der Definition der Funktion main. Sie ist die Einstiegsfunktion eines C-Programms. main wird automatisch als erste Funktion aufgerufen. Anfang und Ende der Funktion main werden durch die beiden geschweiften Klammern markiert.

Die erste Anweisung innerhalb der Funktion main ruft die Funktion puts auf, die den Text „Hallo Welt!“ ausgibt. Die zweite Anweisung return EXIT_SUCCESS; beendet den Funktionsaufruf und legt den Rückgabewert fest. Damit wird der „Erfolgsstatus“ des ausgeführten Programms zum Ausdruck gebracht. Der Wert EXIT_SUCCESS bedeutet hier fehlerfreie Ausführung.

In der letzten Zeile folgt auf die schließende geschweifte Klammer ein Kommentar, eingeschlossen durch die Zeichenfolgen /* und */. Kommentare werden bei der Übersetzung ignoriert; sie sind in erster Linie für den menschlichen Leser gedacht, können aber auch von automatischen Software-Dokumentationswerkzeugen ausgewertet werden.

Die Standardbibliothek[Bearbeiten]

Die C-Standard-Bibliothek ist integraler Bestandteil einer gehosteten (engl. hosted) C-Implementation. Sie enthält unter anderem Makros und Funktionen, die mittels der Standard-Header-Datei verfügbar gemacht werden. Auf freistehenden (engl. freestanding) Implementationen dagegen kann der Umfang der Standardbibliothek eingeschränkt sein.

Die Standardbibliothek ist aufgeteilt in mehrere Standard-Header-Dateien, die hinzugelinkte Bibliothek ist jedoch oft eine einzige große Datei.

  • „Gehostet“: C-Compiler und Programm befinden sich in einer Betriebssystem-Umgebung, welche übliche Dienste bietet (z. B. ein Dateisystem, textuelle Ein- und Ausgabekanäle, Speichermanagement).
  • „Freistehend“: Das C-Programm läuft nicht unter einem Betriebssystem, sondern muss alle Gerätefunktionen selbst implementieren. Häufig stehen dennoch zumindest einige Bibliotheken vorab zur Verfügung. Hier finden häufig Cross-Compiler (auch „Target-Compiler“) Verwendung.

Siehe auch[Bearbeiten]

Literatur[Bearbeiten]

Weblinks[Bearbeiten]

 Wikibooks: C-Programmierung – Lern- und Lehrmaterialien

Einzelnachweise[Bearbeiten]

  1. a b c Dennis M. Ritchie: The Development of the C Language (PDF; 60 kB) Lucent Technologies. January 1993. Abgerufen am 10. August 2012: „The scheme of type composition adopted by C owes considerable debt to Algol 68, although it did not, perhaps, emerge in a form that Algol's adherents would approve of.“
  2. a b Agner Fog: Calling conventions for different C++ compilers and operating systems: Chapter 3, Data Representation (PDF; 416 kB) 16. Februar 2010. Abgerufen am 30. August 2010.
  3. Ken Thompson: Users' Reference to B. Abgerufen am 10. August 2013.
  4. Sprachdefinition von C11 als ISO-Standard ISO/IEC 9899:2011, veröffentlicht am 8. Dezember 2011.
  5. ISO aktualisiert C-Standard, Artikel auf heise online, vom 22. Dezember 2011.
  6. Markus Bautsch: Cycles of Software Crises - How to avoid insecure and uneconomic software, ENISA Quartely, Vol. 3, No. 4, Oct-Dec 2007, p. 3-5
  7. Lambert Kenneth Louden: Programming Languages: Principles and Practices, Ch. 8.6.1 Type Compatibility / 8.7 Type Conversion, Cengage Learning (2011), ISBN 9781133387497
  8. Scheler, Stilkerich, Schröder-Preikschat: Komponenten/Module (PDF; 1,1 MB)
  9. Bertrand Meyer: Objektorientierte Softwareentwicklung. Hanser, Wien, München; Prentice Hall Internat. 1990, S. 406 ISBN 3-446-15773-5.
  10. Eric Giguere: The ANSI Standard: A Summary for the C Programmer. 18. Dezember 1987. Abgerufen am 4. September 2010.
  11. Randy Meyers: The New C: Integers in C99, Part 1. drdobbs.com. 1. Dezember 2000. Abgerufen am 4. September 2010.
  12. Klaus Schmaranz: Softwareentwicklung in C, Springer, 2001, Seite 29 ff.
  13. Helmut Herold und Wolfgang Unger: "C"-Gesamtwerk, te-wi Verlag, 2. Auflage, München, 1992, 2-5 bis 2-7
  14. ISO/IEC 9899:1999 Kapitel 7.6.2 Absatz 3