Zum Inhalt springen

„C (Programmiersprache)“ – Versionsunterschied

aus Wikipedia, der freien Enzyklopädie
[ungesichtete Version][gesichtete Version]
Inhalt gelöscht Inhalt hinzugefügt
K Änderungen von 141.68.25.11 (Diskussion) auf die letzte Version von Curtis Newton zurückgesetzt
Markierung: Zurücksetzung
 
Zeile 1: Zeile 1:
{{Infobox Programmiersprache
Die [[Programmiersprache]] '''C''' wurde von [[Ken Thompson]] und [[Dennis Ritchie]] in den frühen [[1970er|70er]] Jahren für das neu entwickelte Betriebssystem [[Unix]] entworfen. [[Ken Thompson]] passte zunächst die Programmiersprache [[BCPL]] auf seine Bedürfnisse an und nannte die so entstandene Sprache "[[B (Programmiersprache)|B]]" (nach den [[Bell Laboratories]], in denen die Sprache entwickelt wurde). Aus dieser Sprache entstand dann C. Die grundlegenden [[Computerprogramm|Programme]] aller [[Unix]]-Systeme und die [[Kernel|Kernel]] vieler [[Betriebssystem]]e sind in C programmiert.
| Name = C
| Logo = [[Datei:The C Programming Language logo.svg|200px]]
| Beschreibung = Logo der Programmiersprache C
| Paradigma = [[Imperative Programmierung|imperativ]], [[Strukturierte Programmierung|strukturiert]]
| Erscheinungsjahr = 1972
| Entwickler = [[Dennis Ritchie]] & [[Bell Laboratories|Bell Labs]]
| AktuelleVersion =
| AktuelleVersionFreigabeDatum =
| Typisierung =
| Implementierung = [[GNU Compiler Collection|GCC]], [[Microsoft Visual C++|MSVC]], [[Turbo C|Borland C]], Portland Group, [[Intel C++ Compiler|Intel]], [[Clang]]
| Dialekte =
| Beeinflusst_von = [[B (Programmiersprache)|B]], [[BCPL]], [[Algol 68]]<ref name="dmr_quote_algol">{{Internetquelle |autor=Dennis M. Ritchie |url=http://csapp.cs.cmu.edu/3e/docs/chistory.html |titel=The Development of the C Language |hrsg=Lucent Technologies |datum=1993-01 |abruf=2015-09-10 |zitat=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.}}</ref>
| Beeinflusste = [[awk]], [[C++]], [[C−−]], [[C-Sharp|C#]], [[Objective-C]], [[D (Programmiersprache)|D]], [[Go (Programmiersprache)|Go]], [[Java (Programmiersprache)|Java]], [[JavaScript]], [[PHP]], [[Perl (Programmiersprache)|Perl]], [[Python (Programmiersprache)|Python]], [[Vala (Programmiersprache)|Vala]], [[Seed7]]
| Betriebssystem =
| Lizenz =
| Website =
}}


'''C''' ist eine [[Imperative Programmierung|imperative]] und [[Prozedurale Programmierung|prozedurale]] [[Programmiersprache]], die der Informatiker [[Dennis Ritchie]] in den frühen 1970er Jahren an den [[Bell Laboratories]] entwickelte. Seitdem ist sie eine der am weitesten verbreiteten Programmiersprachen.
Die Sprache [[C-Plusplus|C++]] ist aus C hervorgegangen und gegenüber C unter anderem um Möglichkeiten zur [[objektorientierte Programmierung|objektorientierten]] und [[generische Programmierung|generischen]] Programmierung erweitert.


Die Anwendungsbereiche von C sind sehr verschieden. Sie wird zur [[Systemprogrammierung|System-]] und [[Softwaretechnik|Anwendungsprogrammierung]] eingesetzt. Die grundlegenden [[Computerprogramm|Programme]] aller [[Unix]]-Systeme und die [[Kernel (Betriebssystem)|Systemkernel]] vieler [[Betriebssystem]]e sind in C programmiert. Zahlreiche Sprachen, wie [[C++]], [[Objective-C]], [[C-Sharp|C#]], [[D (Programmiersprache)|D]], [[Java (Programmiersprache)|Java]], [[JavaScript]], [[Linden Scripting Language|LSL]], [[PHP]], [[Vala (Programmiersprache)|Vala]] oder [[Perl (Programmiersprache)|Perl]], orientieren sich an der [[Syntax]] und anderen Eigenschaften von C.
==Überblick==
C ist eine Programmiersprache, die auf fast allen [[Computer]]systemen zur Verfügung steht. Im Gegensatz zu z.B. [[BASIC]] gibt es seit der Definition von [[ANSI C]] relativ einheitliche [[Implementierung]]en auf den verschiedenen [[Plattform_(Computer)|Plattform]]en. In jedem C-System mit Laufzeitumgebung steht auch die genormte [[Standard C Library]] zur Verfügung. Dies und die bei geschickter Programmierung hohe Leistung der resultierenden Programme erklärt die weiterhin relativ hohe Popularität der Sprache, sowohl im kommerziellen als auch im [[Open-Source]]-Bereich.


== Geschichte ==
Es gibt Meinungen, C entspreche nicht dem heutigen Stand der Technik; manchmal wird C auch als [[Portierung|portierbarer]] ''Highlevel''-[[Assembler (Informatik)|Assembler]] bezeichnet. Die Kerne fast aller heute verbreiteten Betriebssysteme wurden aber in C implementiert, und dies, obwohl [[C-Plusplus|C++]] bereits seit Mitte der [[1980er|80er]] Jahre zur Verfügung steht, wenn auch in der jetzigen, ISO-genormten Form erst seit 1998.
[[Datei:Ken Thompson and Dennis Ritchie.jpg|gerahmt|[[Ken Thompson]] (links) und [[Dennis Ritchie]] (rechts)]]


=== Entstehung ===
C eignet sich gut für die [[Systemprogrammierung]]. Anders sieht die Sache jedoch bei der [[Anwendungsentwicklung]] aus. Dort wird C zunehmend durch die Sprachen [[C-Plusplus|C++]], [[Java (Programmiersprache)|Java]] und [[C-Sharp|C#]] verdrängt, die gemeinsam haben, dass sie alle über Möglichkeiten zur objektorientierten Programmierung verfügen und C im Bezug auf [[Wartbarkeit]], [[Entwurf]]sunterstützung und [[Abstraktionsniveau]] erweitern und verbessern.
C wurde 1969–1973 von [[Dennis Ritchie]]<ref name="dmr">{{Internetquelle |autor=Dennis M. Ritchie |url=http://csapp.cs.cmu.edu/3e/docs/chistory.html |titel=The Development of the C Language |hrsg=Lucent Technologies |datum=1993-01 |abruf=2015-09-10}}</ref> in den [[Bell Laboratories]] für die Programmierung des damals neuen [[Unix]]-Betriebssystems entwickelt. Er stützte sich dabei auf die Programmiersprache [[B (Programmiersprache)|B]], die er und [[Ken Thompson]] in den Jahren 1969/70 geschrieben hatten&nbsp;– 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.<ref>{{Internetquelle |autor=Ken Thompson |url=https://www.talisman.org/b-manual.html |titel=Users’ Reference to B |abruf=2015-05-30}}</ref> Ursprünglich war der Name NB („New B“) vorgesehen, daraus wurde schließlich C.<ref>''Die Unix-Story.'' Geschichtliches Sachbuch über das Computerbetriebssystem [[Unix]] von Autor [[Brian W. Kernighan]], 254 Seiten, Oktober 2020, [[dpunkt.verlag]] GmbH, Heidelberg, S. 97</ref> Ritchie schrieb auch den ersten [[Compiler]] für C. 1973 war die Sprache so weit ausgereift, dass man nun den Unix-Kernel für die [[PDP-11]] neu in C schreiben konnte.


=== Weitere Entwicklung ===
An anderer Stelle zeigen sich die einfache Struktur und der kleine Umfang der Sprache als großer Vorteil: Die [[Portierung]] eines C-Compilers auf eine neue Prozessorplattform ist verglichen mit anderen Sprachen wenig aufwändig, so dass sich dies vom einfachsten [[Mikrocontroller]] bis zum [[Großrechner-Prozessor]] praktisch immer lohnt. Der GNU C-Compiler [[gcc]] ist beispielsweise für eine Vielzahl unterschiedlichster Prozessoren und Betriebssysteme verfügbar. Für den Entwickler bedeutet dies, dass unabhängig von der Zielplattform fast immer auch ein C-Compiler für diese spezifische Plattform existiert. Die prozessorspezifische Programmierung in Assembler bleibt ihm dadurch ganz oder weitgehend erspart, und Quellcode, der für andere Plattformen geschrieben wurde, kann oftmals mit keinen oder nur wenigen Änderungen auf einer neuen Plattform weiterverwendet werden.
K&R C erweiterte die Sprache um neue Schlüsselwörter wie <code>long</code> oder <code>unsigned</code> und führte die von Mike Lesk entwickelte I/O-Standardbibliothek und auf Empfehlung von Alan Snyder den [[Präprozessor]] ein.


== Standards ==
Die Sprachbeschreibung wurde [[1972]] erstmals publiziert. Im Jahre [[1989]] wurde die Sprache erstmals standardisiert ([[Varianten der Programmiersprache C|C89]]). Dieser Standard wurde überarbeitet und [[1999]] erschien dann der internationale Standard [[ISO/IEC 9899:1999]], der als C99 bekannt ist. ''Siehe auch [[Varianten der Programmiersprache C]]''.
{{Hauptartikel|Varianten der Programmiersprache C}}
C ist eine [[Programmiersprache]], die auf fast allen [[Computersystem]]en zur Verfügung steht. Um den Wildwuchs zahlreicher Dialekte einzudämmen, wurde C mehrfach standardisiert ([[Varianten der Programmiersprache C#C89, C90|C89/C90]], [[Varianten der Programmiersprache C#C99|C99]], [[Varianten der Programmiersprache C#C11|C11]]). Abgesehen vom [[Mikrocontroller]]bereich, wo eigene Dialekte existieren, sind die meisten aktuellen PC-/Server-[[Implementierung]]en 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 hardwarenahe Programmierung enthalten, in der Regel gut auf andere Zielsysteme portiert werden.


Das Normungsgremium von C ist die [[ISO]]/[[International Electrotechnical Commission|IEC]] – Arbeitsgruppe JTC1/SC22/WG14 – C, kurz als ''WG14'' bekannt.
Ein ausführbares C-[[Computerprogramm|Programm]] wird durch den so genannten [[Linker]] oder [[Linker|Binder]] aus [[Objektcode]] erzeugt (gebunden). Dabei können mehrere Objektcodedateien zu einem [[Computerprogramm|Programm]] zusammengefasst werden. Die Objektcodedateien ihrerseits werden durch den [[Compiler]] aus [[Textdatei]]en erzeugt (übersetzt), die eine Anzahl Funktions- und Variablendefinitionen enthalten. Neben Programmen kann man aber auch noch Bibliotheken erstellen. Diese werden ähnlich wie [[Computerprogramm|Programme]] gebunden oder in ein Archiv zusammengefasst. Diese Bibliotheken können dann in einem späteren Bindevorgang wiederum zu einem [[Computerprogramm|Programm]] hinzugebunden werden. Auf diese Weise kann man verhindern, dass für jedes zu erzeugende Programm unzählige (in größeren Systemen durchaus hunderte bis tausende) unveränderliche Objektcodedateien immer wieder erneut gebunden werden müssen.
Die nationalen Standardisierungsorganisationen übernehmen die Veröffentlichungen des internationalen Standards in an ihre Bedürfnisse angepasster Form.


[[Datei:The C Programming Language, First Edition Cover (2).svg|mini|Die 1978 erschienene erste Auflage von ''[[The C Programming Language]]'' beinhaltet den ehemaligen inoffiziellen Standard K&R C]]
Das Design der Programmiersprache, die Technik des Linkens und verschiedene zu festen Sprachelementen gewordene Funktionen und Festlegungen sind eng mit dem Design [[Unix|unixartiger]] Betriebssysteme verbunden, so die Art und Weise der Signalbearbeitung, der Ein- und Ausgabe mit [[Stream]]s, und das Verfahren des Startens und Beendens eines Programms.


== [[Hallo-Welt-Programm]] in C ==
=== K&R C ===
Bis ins Jahr 1989 gab es keinen offiziellen Standard der Sprache. Seit 1978 galt hingegen das Buch ''[[The C Programming Language]]'' als informeller De-facto-Standard, welches [[Brian W. Kernighan]] und Dennis Ritchie im selben Jahr veröffentlicht hatten.<ref>Brian W. Kernighan, Dennis M. Ritchie: ''The C Programming Language'', Prentice Hall, Englewood Cliffs (NJ) 1978, ISBN 0-13-110163-3.</ref> Bezeichnet wird diese Spezifikation als K&R C.


Da in den folgenden Jahren die Zahl an Erweiterungen der Sprache ständig wuchs, man sich nicht auf eine gemeinsame Standard-Bibliothek einigen konnte und nicht einmal die UNIX-Compiler K&R C vollständig implementierten, wurde beschlossen, einen offiziellen Standard festzulegen. Nachdem dieser schließlich im Jahr 1989 erschienen war, blieb K&R C zwar noch für einige Jahre De-facto-Standard vieler Programmierer, verlor dann aber rasch an Bedeutung.
Der folgende Quelltext stellt ein einfaches C-Programm dar, das die Meldung <code>Hallo Welt!</code> und einen Zeilenumbruch auf der Standardausgabe ausgibt.


=== ANSI C ===
<code>
Im Jahr 1983 setzte das [[American National Standards Institute]] (ANSI) ein Komitee namens X3J11 ein, das 1989 seine Arbeit abschloss und die Norm ''ANSI X3.159-1989 Programming Language C'' verabschiedete. Diese Version der Sprache C wird auch kurz als ANSI C, Standard C oder C89 bezeichnet.
#include <stdio.h>
int main (void)
{
printf("Hallo Welt!\n");
return 0;
}
</code>


Ein Jahr später übernahm die [[International Organization for Standardization]] (ISO) den bis dahin rein amerikanischen Standard auch als internationale Norm, die ''ISO/IEC 9899:1990'', kurz auch als C90 bezeichnet. Die Namen C89 und C90 beziehen sich also auf dieselbe Version von C.
''Erläuterung:'' In der ersten Zeile wird durch <code>#include &lt;stdio.h></code> die Verwendung der Ein-/Ausgabe-Bibliothek ''stdio'' und damit der Funktion <code>printf</code> ermöglicht. <code>stdio.h</code> ist eine so genannte [[Headerdatei]]. Sie enthält u.a. den [[Funktionsprototyp|Prototyp]] von <code>printf</code> und wird durch den [[Präprozessor]] eingefügt. Danach kann der Compiler Aufrufe für <code>printf</code> generieren, ohne ihren tatsächlichen Code zu kennen, der erst beim Linken geliefert wird. Dies gilt für die überwiegende Mehrheit aller C-Systeme.


Nach der ersten Entwicklung durch ANSI und ISO wurde der Sprachstandard für einige Jahre kaum geändert. Erst 1995 erschien das ''Normative Amendment 1'' zu C90. Es hieß ''ISO/IEC 9899/AMD1:1995'' und wird auch kurz als C95 bezeichnet. Neben der Korrektur einiger Details wurden mit C95 internationale Schriftsätze besser unterstützt.
In der dritten Zeile (die zweite ist eine Leerzeile, von der beliebig viele existieren können) beginnt der eigentliche Programmablauf mit dem Aufruf der [[Funktion (Programmierung)|Funktion]] <code>main</code>. Sie ist die Hauptfunktion eines C-Programmes und in diesem kleinen Programm sogar die einzige. <code>main</code> wird immer als erste Funktion aufgerufen und hat wie alle Funktionen einen Anfang (die öffnende geschweifte Klammer) und ein Ende (die schließende geschweifte Klammer).


=== C99 ===
Die erste Anweisung in der Funktion <code>main</code> ist eine Ausdrucksanweisung welche die Funktion <code>printf</code> aufruft. Diese Funktion ist nicht Teil des [[#Beschreibung der Sprache|Sprachkerns]], sondern der [[#Die Standardbibliothek|Standardbibliothek]]. Daher muss sie (gemäß [[C99]]) vor ihrer Verwendung deklariert werden. Dies geschieht durch die Präprozessordirektive <code>#include &lt;stdio.h></code>, die in der ersten Zeile angegeben wurde. Die Funktionen der Standardbibliothek werden in aller Regel durch eine Bibliothek mit Hilfe eines [[Linker]]s an das Programm gebunden, jedoch kann ein Compiler auch auf einem anderen Weg die Funktion <code>printf</code> zur Verfügung stellen.


Nach einigen kleineren Revisionen erschien im Jahr 1999 der neue Standard ''ISO/IEC 9899:1999'', kurz C99. Er war größtenteils mit C90 kompatibel und führte einige neue, teilweise von C++ übernommene Features ein, von denen einige bereits zuvor von verschiedenen Compilern implementiert worden waren. C99 wurde im Lauf der Jahre durch drei ''Technical Corrigendas'' ergänzt.
Die zweite Anweisung ist die Sprung-Anweisung <code>return 0;</code>. Die <code>return</code>-Anweisung ist Teil des Sprachkerns. Für sie ist ein Header (<code>#include...</code>), wie dies bei <code>printf</code> der Fall war, nicht nötig. Der Rückgabewert <code>0</code> soll von dem Aufrufer des Programms als ''fehlerfreie Ausführung'' interpretiert werden.Alternativ kann man auch <code> return EXIT_SUCCESS; </code> benutzen. Dazu
wird allerdings der Header <code> stdlib.h </code> benötig, in welchen das [[Makro]] ''EXIT_SUCCESS'' definiert ist. Diese [[Makro]] wird dann vom [[Präprozessor]] in den systemspezifischen Wert für
eine ''fehlerfreie Ausführung'' expandiert.


=== C11 ===
Man kann der Funktion <code>main</code> beim Aufruf Werte übergeben, die dann zwischen den runden Klammern angegeben werden. Man spricht dabei auch von ''Parameterliste''. Wird <code>void</code> zwischen den Klammern angegeben, so ist dies gleichbedeutend mit ''keine Parameter''. Fügt man hingegen den Text ''int argc, char* argv[]'' in die Parameterliste ein, lässt sich während des Programmablaufs mittels der Ganzzahlvariable ''argc'' die Anzahl der beim Programmstart übergebenen Argumente abfragen:
Im Jahr 2007 begann die Entwicklung eines neuen Standards mit dem inoffiziellen Arbeitstitel ''C1X''. Er wurde im Dezember 2011 veröffentlicht und ist in der Kurzform als C11 bekannt. Neben einer besseren Kompatibilität mit C++ wurden der Sprache wiederum neue Features hinzugefügt.<ref name="isoC11">[http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=57853 Sprachdefinition von C11 als ISO-Standard ISO/IEC 9899:2011], veröffentlicht am 8. Dezember 2011.</ref><ref name="heiseC11">[http://heise.de/-1400349 ISO aktualisiert C-Standard], Artikel auf heise online, vom 22. Dezember 2011.</ref>


=== C18 ===
<code>
Diese Norm entspricht der von C11 mit der Ausnahme von Fehlerkorrekturen und einem neuen Wert von __STDC_VERSION__ und wird daher im selben Umfang wie C11 unterstützt.<ref>{{Internetquelle |url=https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html |titel=Options Controlling C Dialect |abruf=2018-09-08}}</ref>
int main (int argc, char* argv[])
Der Standard wurde im Juni 2018 unter der Norm ''ISO/IEC 9899:2018'' freigegeben.<ref>{{Internetquelle |url=https://www.iso.org/standard/74528.html |titel=ISO/IEC 9899:2018 Programming languages C |abruf=2018-09-08}}</ref>
{
/* ... */
}
</code>


== Verwendung ==
Ein Zugriff auf die Zeichenketten-Reihung ''argv[]'' ermöglicht die Abfrage des n-ten Arguments, wobei hierzu eine Ganzzahl zwischen 0 und n-1 in die eckigen Klammern von ''argv[]'' einzusetzen ist. Nach der Abarbeitung erhält man von der Funktion <code>main</code> einen Wert zurück. Dieser Wert ist vom Typ <code>int</code>. Typ <code>int</code> bedeutet, dass eine vorzeichenbehaftete Ganzzahl zurückgeliefert wird.
[[Datei:The C Programming Language.png|mini|The C Programming Language]]
Trotz des eher hohen Alters ist die Sprache C auch heute weit verbreitet und wird sowohl im Hochschulbereich als auch in der Industrie und im [[Open Source|Open-Source]]-Bereich verwendet.<ref>Rolf Isernhagen, Hartmut Helmke: ''Softwaretechnik in C und C++. Das Kompendium. Modulare, objektorientierte und generische Programmierung. ISO-C90, ISO-C99, ISO-C++98, MS-C++.NET''. 4., vollständig überarbeitete Auflage, Hanser, München/Wien 2004, ISBN 3-446-22715-6, Seite 4.</ref>


=== System- und Anwendungsprogrammierung ===
==Programmieren in C==
Das Haupteinsatzgebiet von C liegt in der [[Systemprogrammierung]], insbesondere von [[Eingebettetes System|eingebetteten Systemen]], [[Gerätetreiber|Treibern]] und [[Kernel (Betriebssystem)|Betriebssystemkernen]]. 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 eine Laufzeitumgebung zu haben.


Auch [[Anwendungssoftware]] wird oft in C erstellt, wobei die Relevanz der Sprache hier hinter andere zurückfiel, das ist besonders deutlich auf mobilen Plattformen. Viele Programmierschnittstellen für Anwendungsprogramme und Betriebssystem-[[Programmierschnittstelle|APIs]] werden in Form von C-Schnittstellen implementiert, zum Beispiel [[Win32]].<ref>[https://docs.microsoft.com/en-us/previous-versions/bb384843(v=vs.140) ''Walkthrough: Creating Windows Desktop Applications (C++)''] Microsoft Docs, abgerufen am 5. Dezember 2019.</ref>
Die Programmierung mit der Sprache C kann nach vier Kriterien unterteilt werden:


=== Implementierung anderer Sprachen ===
* Der erste Betrachtungspunkt ist ''die Sprache selbst''. Also der Kern der Sprache, der vom [[Compiler]] direkt verstanden wird. Der Sprachkern wird in dem Kapitel zur [[#Beschreibung der Sprache|Beschreibung der Sprache]] genauer erklärt werden.
Wegen der hohen Ausführungsgeschwindigkeit und geringen Codegröße werden [[Compiler]], [[Programmbibliothek]]en und [[Interpreter]] anderer höherer Programmiersprachen (wie z.&nbsp;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 verwendet, um ohne maschinenspezifische Entwicklung für den [[Codegenerator]] die Portabilität zu erhöhen (C-Compiler existieren für nahezu jede Plattform).
* Die Bibliotheksfunktionen, die in ''jedem'' ("hosted") C-Compiler zur Verfügung stehen, solange der Compiler den Anspruch hat, ANSI-kompatibel zu sein. Verwendet ein Programm lediglich den Sprachkern gemäß der Sprachdefinition und [[Standard C Library|die Standardbibliothek]], so ist es auf jedem System, das einen ANSI-kompatiblen Compiler zur Verfügung stellt, übersetzbar und zeigt auch auf allen Systemen das gleiche Verhalten.
Einige Compiler, die C auf diese Art benutzen, sind [[Chicken (Scheme)|Chicken]], [[Eiffel (Programmiersprache)|EiffelStudio]], [[Esterel (Programmiersprache)|Esterel]], [[PyPy]], [[Sather]], [[Squeak]] und [[Vala (Programmiersprache)|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−−]].
* Die Bibliotheksfunktionen, die ''von dem (Betriebs-)System'' zur Verfügung gestellt werden. Diese Bibliotheken stammen also nicht von einem ANSI-kompatiblen Compiler. Daher sind Programme, die diese Bibliotheken verwenden, nur bedingt [[Portierung|portabel]]. Ein Teil dieser Bibliotheken wird in dem Kapitel ''[[#Weitere C-Bibliotheken|Weitere C-Bibliotheken]]'' beschrieben.


C wird oft für die Erstellung von ''Anbindungen'' (englisch bindings) genutzt (zum Beispiel [[Java Native Interface]]). Diese Anbindungen erlauben es Programmen, die in einer anderen [[Höhere Programmiersprache|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.&nbsp;B. [[mod perl]]).
* Die Erweiterungen des Sprachkerns, die von einem Compiler zur Verfügung gestellt werden. Diese Erweiterungen betreffen die [[#Werkzeuge|Werkzeuge]].


== Syntax ==
===Beschreibung der Sprache===
C ist [[Case sensitivity|case-sensitiv]].


Außerdem besitzt C eine sehr kleine Menge an [[Schlüsselwort (Programmierung)|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 Funktionen der [[C-Standard-Bibliothek]] realisiert werden (zum Beispiel die Ein- und Ausgabe über Konsole oder Dateien, dynamische Speicherverwaltung usw.).
Die Beschreibung der Sprache bezieht sich auf das Kapitel ''6. Language'' in [[C99]].


In C89 gibt es 32 Schlüsselwörter:
* Konzepte
{{Mehrspaltige Liste |breite=10em |liste=
** Geltungsbereich von Bezeichnern
:<code>auto</code>
** Bindung von Bezeichnern
:<code>break</code>
** Speicherdauer von Objekten
:<code>case</code>
** Typen
:<code>char</code>
:<code>const</code>
:<code>continue</code>
:<code>default</code>
:<code>do</code>
:<code>double</code>
:<code>else</code>
:<code>enum</code>
:<code>extern</code>
:<code>float</code>
:<code>for</code>
:<code>goto</code>
:<code>if</code>
:<code>int</code>
:<code>long</code>
:<code>register</code>
:<code>return</code>
:<code>short</code>
:<code>signed</code>
:<code>sizeof</code>
:<code>static</code>
:<code>struct</code>
:<code>switch</code>
:<code>typedef</code>
:<code>union</code>
:<code>unsigned</code>
:<code>void</code>
:<code>volatile</code>
:<code>while</code>
}}


Mit C99 kamen fünf weitere dazu:
* [[lexikalisch]]e Elemente
{{Mehrspaltige Liste |breite=25em |liste=
** Schlüsselwörter
:<code>_Bool</code>
** Bezeichner
:<code>_Complex</code>
** Konstanten
:<code>_Imaginary</code>
** Kommentare
:<code>inline</code>
:<code>restrict</code>
}}


Mit C11 kamen sieben weitere hinzu:
* Deklarationen / Definition
{{Mehrspaltige Liste |breite=25em |liste=
* Ausdrücke
:<code>_Alignas</code>
* Anweisungen
:<code>_Alignof</code>
* Der Präprozessor
:<code>_Atomic</code>
:<code>_Generic</code>
:<code>_Noreturn</code>
:<code>_Static_assert</code>
:<code>_Thread_local</code>
}}


===Die Standardbibliothek===
=== Hallo-Welt-Programm ===
Eine einfache Version des [[Hallo-Welt-Programm]]s in C ist diejenige, die Ritchie und Kernighan selbst in der zweiten Auflage ihres Buches ''[[The C Programming Language]]'' verwendet haben.<ref>Brian Kernighan, Dennis Ritchie: ''The C Programming Language''. 2. Auflage, Prentice Hall, Englewood Cliffs (NJ) 1988, ISBN 0-13-110362-8, Seite 6.</ref> Zu beachten ist, dass im älteren ANSI C Standard kein Rückgabetyp angegeben werden muss, da der Compiler von einem impliziten int als Rückgabetyp ausgeht.


<syntaxhighlight lang="c">
Die Standardbibliothek ([[Standard C Library]]) beschreibt die [[Makro]]s und [[Funktion (Programmierung)|Funktionen]], die jedem Compiler zur Verfügung steht.
#include <stdio.h>
main()
{
printf("hello, world\n");
}
</syntaxhighlight>


===Weitere C-Bibliotheken===
=== Datentypen ===
{{Hauptartikel|Datentypen in C}}


==== char ====
Die nachfolgend beschriebenen Bibliotheken sind nicht Teil der Sprachbeschreibung von C.
Zum Speichern eines Zeichens (sowie von kleinen Zahlen) verwendet man in C üblicherweise den Datentyp [[Char (Datentyp)|Character]], geschrieben als <code>char</code>.
Daher stehen sie nur zur Verfügung, wenn die [[Application Programming Interface|API]] des Systems sie anbietet.


Vom Computer tatsächlich gespeichert wird nicht das Zeichen (wie zum Beispiel „A“), sondern eine gleichbedeutende mindestens acht [[Bit]] lange Binärzahl (z.&nbsp;B. 01000001). Diese Binärzahl steht im Speicher und kann anhand einer Tabelle jederzeit automatisch in den entsprechenden Buchstaben umgewandelt werden, wobei der aktuelle Zeichensatz bzw. die Codepage der Systemumgebung entscheidend ist. Zum Beispiel steht 01000001 gemäß der [[ASCII-Tabelle]] für das Zeichen „A“.
* [[POSIX (C-Bibliothek)|POSIX - Programmierung einer UNIX-Umgebung]]
* [[PCRE|pcre - Perl Compatible Regular Expressions]]
* [[MySQL (C-Bibliothek)|Zugriff auf eine MySQL-Datenbank]]


Um auch Zeichen aus Zeichensätzen aufnehmen zu können, die mehr Zeichen umfassen als der relativ kleine ASCII-Zeichensatz, wurde mit <code>wchar_t</code> bald ein zweiter für Zeichen konzipierter Datentyp eingeführt.
===Werkzeuge===


<syntaxhighlight lang="c">
*[[gcc|GNU C-Compiler]]
// gespeichert wird nicht das Zeichen „A“, sondern meist ein Byte ("01000001")
*[[GNU Debugger]]
char zeichen = 'A';
<!-- noch zu ergänzen -->


// gibt das Zeichen mit der Ordnungszahl 65 aus (in ASCII ein „A“)
== Bewertung von Sprachmerkmalen ==
printf("%c", 65);
</syntaxhighlight>


=== Stärken ===
==== int ====
Zum Speichern einer [[Ganze Zahl|Ganzzahl]] (wie zum Beispiel 3) verwendet man eine Variable vom Datentyp [[Integer (Datentyp)|Integer]], geschrieben als <code>int</code>. Die Größe eines Integers beträgt heutzutage (je nach [[Prozessorarchitektur]] und Betriebssystem) meist 32 Bit, manchmal noch 16 Bit und fast nie 64 Bit. In 16 Bit lassen sich 65536 verschiedene Werte speichern. Um die Verwendung von negativen Zahlen zu ermöglichen, reicht der Wertebereich bei 16 Bit gewöhnlich von -32768 bis 32767. Werden keine negativen Zahlen benötigt, kann der Programmierer mit <code>unsigned int</code> aber einen vorzeichenlosen Integer verwenden. Bei 16 Bit großen Integern ergibt das einen Wertebereich von 0 bis 65535.
* Minimalistischer [[Sprachumfang]]: Der kleinste bekannte C-Compiler besteht aus 3742 Bytes C-Code und kann sich selbst kompilieren.
* Keine Felder (ersetzt durch Feldkonstanten und Behandlung von Feldern als Zeigerkonstanten)
* Zeigerarithmetik ermöglicht die effiziente Behandlung von Feldzugriffen, Parametern usw.
* Zeiger auf Unterprogramme (Funktionszeiger) in Datenstrukturen speicherbar
* Einfache Variablen nur als [[Wertparameter]], Felder nur als [[Referenzparameter]]
* Referenzparameter für einfache Variablen werden durch [[Zeiger (Informatik)|Zeiger]] ersetzt.
* Hardwarenahe Programmierung ist möglich, direkter Umgang mit [[Bit]]s, [[Byte]]s, direkter [[Speicherzugriff]] und Zeigerarithmetik
* [[Präprozessor]] zur Spracherweiterung und bedingten Übersetzung
* [[Linker]] ([[Linker|Binder]]) (C war eine der ersten Sprachen, die das Einbinden von externen vorübersetzten Routinen in der Sprachdefinition berücksichtigt)
* Viele [[Optimierung]]en sind bei Übersetzung möglich
* Ein C-Compiler ist für nahezu jede Prozessorarchitektur vorhanden, seien es "historische" 8-Bit-Prozessoren und einfache [[Controller|Mikrocontroller]] oder aktuelle 64-Bit-Prozessoren.


Um den Wertebereich eines Integers zu verkleinern oder zu vergrößern, stellt man ihm einen der Qualifizierer <code>short</code>, <code>long</code> oder <code>long long</code> voran. Das Schlüsselwort <code>int</code> kann dann auch weggelassen werden, so ist <code>long</code> gleichbedeutend mit <code>long int</code>. Um zwischen vorzeichenbehafteten und vorzeichenlosen Ganzzahlen zu wechseln, gibt es die beiden Qualifizierer <code>signed</code> und <code>unsigned</code>. Für einen vorzeichenbehafteten Integer kann der Qualifizierer aber auch weggelassen werden, so ist <code>signed int</code> gleichbedeutend mit <code>int</code>. Die [[C-Standard-Bibliothek]] ergänzt diese Datentypen über die plattformunabhängige Header-Datei <code>&lt;stdint.h></code>, in der ein Set von Ganzzahltypen mit fester Länge definiert ist. Obwohl der Datentyp <code>char</code> für Textzeichen vorgesehen ist, können dessen Werte auch als ganze Zahlen mit einem Wertebereich von 0 bis 255 (unsigned) oder von -128 bis +127 (signed) verwendet werden.
=== Schwächen ===
* Fehlendes Modulkonzept (wird üblicherweise durch Paare von .c- und .h-Dateien notdürftig nachgebaut)
* Nur eingeschränkt typsicher
* Die Sprachdefinition besitzt Lücken (Verhalten undefiniert)
* Verglichen mit anderen prozeduralen Sprachen wie (das ältere!) [[Pascal (Programmiersprache)|Pascal]] oder [[Modula-2]] zu wenig klare Syntax, was zu sehr komplexen und fehleranfälligen Compilern führt
* "Wilde" Zeiger
** Man kann Zeiger auf beliebige Stellen des Speichers richten. Insbesondere zeigen nicht explizit initialisierte [[Stack]]-Variablen oft auf beliebige Stellen des Speichers. Die Folge sind schwer zu diagnostizierende Fehler.
* Felder
** C kennt zwar den Datentyp Feld und erlaubt sogar die Definition von Feldern, die mit Konstanten vorbelegt sind. Intern werden Felder jedoch immer als Zeiger verwaltet. Dies bedeutet, dass eine eventuell nötige dynamische Speicherverwaltung von Feldern vom Programmierer implementiert werden muss. Auch die [[Array|Feld]]<nowiki></nowiki>größe wird beim Zugriff nicht überprüft. Durch [[Programmierfehler]] können Speicherbereiche durch illegale Feldzugriffe während der [[Laufzeit]] unabsichtlich oder gezielt ([[Pufferüberlauf]]) verändert werden.
** Mehrdimensionale Felder werden in der numerischen Mathematik für Matrizen benötigt. Dafür ist die Struktur der C-Felder jedoch völlig ungeeignet. In Numerical Recipes in C, Kap. 1.2, Seite 20 ff ([http://www.library.cornell.edu/nr/bookcpdf/c1-2.pdf online lesbar!]) wird dieses Problem diskutiert und die in diesem Buch verwendete Lösung erläutert. Natürlich ist es auch eine Stärke von C, dass eine derartige Schwäche überhaupt durch eine Lösung ausgeglichen werden kann, die darüberhinaus auch noch elegant ist.
* Zeichenketten
** C kennt Strings, die nach den Grundsätzen der 60er Jahre durchaus in ein Gesamtkonzept integriert sind. Sie werden als so genannte nullterminierte Strings in Variablen und Konstanten ("Hallo") gespeichert und durch ihre Adressen (Zeiger!) verwendet. Die große Schwäche dieses Konzepts liegt in der großen Programmiererverantwortung, denen reale Programmierer nicht immer gewachsen sind ([[wilder Zeiger|wilde Zeiger]], zu kleine Felder, vergessene Abschlussnull...)
** C hat keine integrierten [[Zeichenkette]]n ("Strings"). Statt dessen wird ein Zeichenfeld verwendet, das mit einem Nullzeichen abgeschlossen wird. Die Speicherverwaltung von Zeichenketten muss vom Programmierer vorgenommen werden.
* Speicherverwaltung
** Der Programmierer muss den [[dynamischer Speicher|dynamischen Speicher]] selbst verwalten. Hierzu stehen [[Bibliotheksfunktion]]en zur Verfügung.
* niedriger Abstraktionsgrad
* Portabilitätsprobleme
** C schreibt die Speichergröße verschiedener [[Datentyp|Typen]] in der [[Sprachdefinition]] nicht vor. Dies ermöglicht die [[Portierung]] bestehender Programme auf andere, auch neue [[Prozessor]]en. Es ist nur zugesichert, dass ein short int nicht länger sein darf als ein long int. In den [[1980er]] und [[1990er]] Jahren wurden vorwiegend 32-Bit Systeme wie [[VAX]], [[68000]], [[i386]] eingesetzt. Bei diesen waren Zeiger, ''int'' und ''long'' alle 32 Bits lang, so dass sich dies als Quasistandard etabliert hat. Dies bereitet Probleme bei der [[Portierung]] auf modernere [[64-Bit-Architektur]]en, falls der Programmierer von bestimmten Längen ausgegangen ist.
** Einige weitere Eigenschaften der Sprachdefinition (Ergebnistyp bei Zeigersubtraktion, Ausrichtung ([[Alignment]]) von Datentypen) bereiten ebenfalls Probleme, wenn statt der empfohlenen abstrakten Typen (wie ''ptrdiff_t'' für Zeigersubtraktionen, ''size_t'' für Größen von Speicherbereichen) direkt fundamentale Typen wie ''int'' verwendet werden.
** In der Sprachversion [[C99]] sind Datentypen mit expliziten Bit-Längen definiert (''int8_t'', ''int16_t'', etc.).


<syntaxhighlight lang="c">
=== Zusammenfassung ===
char ganzzahl = 1; // mindestens 8 Bit, also 256 mögliche Werte
Man kann sagen, dass die größte Stärke von C - die uneingeschränkte Freiheit des Programmierers im Umgang mit Zeigern und Speicherstrukturen - gleichzeitig ihre größte Schwäche ist.
short ganzzahl = 2; // mindestens 16 Bit, also 65536 mögliche Werte
int ganzzahl = 3; // mindestens 16 Bit, also 65536 mögliche Werte
long ganzzahl = 4; // mindestens 32 Bit, also 4294967296 mögliche Werte
long long ganzzahl = 5; // mindestens 64 Bit, also 18446744073709551616 mögliche Werte
</syntaxhighlight>


==== float und double ====
Da der freizügige Umgang der Programmiersprache mit dem Speicher in kritischen Umgebungen ([[Kreditinstitut]]en, [[Börse]]n, [[Versicherung]]en, [[Raumfahrt]] usw.) leicht hohe Schäden nach sich ziehen kann, wird hier mittlerweile ernsthaft erwogen, diese Programmiersprache bei neuen Projekten zu verbieten.
Zahlen mit [[Nachkommastellen]] werden in einem der drei Datentypen <code>float</code>, <code>double</code> und <code>long double</code> gespeichert. In den meisten C-Implementierungen entsprechen die Datentypen float und double dem international gültigen Standard für binäre Gleitpunktarithmetiken (IEC 559, im Jahr 1989 aus dem älteren amerikanischen Standard [[IEEE 754]] hervorgegangen). Ein float implementiert das „[[Einfache Genauigkeit|einfach lange Format]]“, ein double das „[[Doppelte Genauigkeit|doppelt lange Format]]“. Dabei umfasst ein float 32 Bit, ein double 64 Bit. doubles sind also genauer. Floats werden aufgrund dieses Umstands nur noch in speziellen Fällen verwendet. Die Größe von long doubles ist je nach Implementierung unterschiedlich, ein long double darf aber auf keinen Fall kleiner sein als ein double. Die genauen Eigenschaften und Wertebereiche auf der benutzten Architektur können über die Header-Datei <code>&lt;float.h></code> ermittelt werden.


<syntaxhighlight lang="c">
// Genauigkeit ist jeweils implementierungsabhängig


float kommazahl = 0.000001f;
double kommazahl = 0.000000000000002;
long double kommazahl = 0.3l;
</syntaxhighlight>

==== void ====
{{Hauptartikel|void (Schlüsselwort)}}
Der Datentyp <code>void</code> wird im C-Standard als „unvollständiger Typ“ bezeichnet. Man kann keine Variablen von diesem Typ erzeugen. Verwendet wird <code>void</code> erstens, wenn eine Funktion keinen Wert zurückgeben soll, zweitens wenn explizit eine leere Parameterliste für eine Funktion verlangt wird und drittens, wenn ein Zeiger auf „Objekte beliebigen Typs“ zeigen soll.

<syntaxhighlight lang="c">
// Deklaration einer Funktion, die keinen Wert zurückgibt
void funktionsname();

// Deklaration einer Funktion, die int zurückgibt und keine Parameter akzeptiert
int funktionsname(void);

// Zeiger auf ein Objekt von beliebigem Typ
void* zeigername;
</syntaxhighlight>

==== Zeiger ====
{{Hauptartikel|Zeiger (C)}}

Wie in anderen Programmiersprachen sind [[Zeiger (Informatik)|Zeiger]] in C Variablen, die statt eines direkt verwendbaren Wertes (wie das Zeichen „A“ oder die Zahl 5) eine Speicheradresse (wie etwa die Adresse 170234) speichern. Die Adressen im Speicher sind durchnummeriert. An der Speicheradresse 170234 könnte zum Beispiel der Wert 00000001 gespeichert sein (Binärwert der Dezimalzahl 1). Zeiger ermöglichen es, auf den Wert zuzugreifen, der an einer Speicheradresse liegt. Dieser Wert kann wiederum eine Adresse sein, die auf eine weitere Speicheradresse zeigt. Bei der Deklaration eines Zeigers wird zuerst der Datentyp des Objekts angegeben, auf das gezeigt wird, danach ein [[Sternchen (Schriftzeichen)|Asterisk]], danach der gewünschte Name des Zeigers.

<syntaxhighlight lang="c">
char* zeiger; // kann die Adresse eines Characters speichern
double* zeiger; // kann die Adresse eines Doubles speichern
</syntaxhighlight>

==== Felder ====
{{Hauptartikel|Felder in C}}
Wie in anderen Programmiersprachen verwendet man in C [[Array (Datentyp)|Arrays]], um mehrere Werte desselben Datentyps zu speichern. Die Werte eines Arrays haben aufeinanderfolgende Speicheradressen. Die Anzahl der verschiedenen Werte eines Arrays ist als Index des Feldes festgelegt. Da es in C keinen eigenen Datentyp für [[Zeichenkette|Strings]] gibt, werden Arrays auch verwendet, um Zeichenfolgen zu speichern.

<syntaxhighlight lang="c">
// Definition eines Arrays mit 3 ganzzahligen Werten
int zahlen[] = { 17, 0, 3 };

// Array, das zur Speicherung eines Strings verwendet wird
char string[] = "Hallo, Welt!\n";
</syntaxhighlight>

==== struct ====
{{Hauptartikel|Verbund (Datentyp)}}
Um verschiedenartige Daten in einer Variable zu speichern, verwendet man Structures, geschrieben als <code>struct</code>. Auf diese Weise können Variablen verschiedenen Datentyps zusammengefasst werden.

<syntaxhighlight lang="c">
struct person {
char* vorname;
char nachname[20];
int alter;
double groesse;
};
</syntaxhighlight>

==== enum ====
Wie in anderen Programmiersprachen dient ein [[Aufzählungstyp|Enum]] in C dazu, mehrere konstante Werte zu einem Typ zu kombinieren.

<syntaxhighlight lang="c">
enum Temperatur { WARM, KALT, MITTEL };

enum Temperatur heutige_temperatur = WARM;

if (heutige_temperatur == KALT)
printf("Warm anziehen!"); // wird nicht ausgegeben, da es heute „WARM“ ist
</syntaxhighlight>

==== typedef ====
Das [[Schlüsselwort (Programmierung)|Schlüsselwort]] [[typedef]] wird zur Erstellung eines [[Pseudonym|Alias]] für einen [[Typisierung (Informatik)|Datentyp]] verwendet.

<syntaxhighlight lang="c">
// legt den Alias "Ganzzahl" für den Datentyp "int" an
typedef int Ganzzahl;

// ist jetzt gleichbedeutend zu: int a, b;
Ganzzahl a, b;
</syntaxhighlight>

==== _Bool ====
Bis zum C99-Standard gab es keinen Datentyp zum Speichern eines [[Wahrheitswert]]s. Erst seit 1999 können Variablen als <code>_Bool</code> deklariert werden und einen der beiden Werte 0 (falsch) oder 1 (wahr) aufnehmen.

<syntaxhighlight lang="c">
_Bool a = 1; // seit C99
</syntaxhighlight>
Durch explizite Verwendung der Header-Datei <code>stdbool.h</code> ist die verbreitete Verwendung des logischen Datentyps <code>bool</code> mit den zwei möglichen Ausprägungen <code>true</code> bzw. <code>false</code> möglich:
<syntaxhighlight lang="c">
#include <stdbool.h>

bool a = true; // seit C99
</syntaxhighlight>

==== _Complex und _Imaginary ====
Seit C99 gibt es drei Gleitkomma-Datentypen für [[komplexe Zahl]]en, welche aus den drei Gleitkommatypen abgeleitet sind: <code>float _Complex</code>, <code>double _Complex</code> und <code>long double _Complex</code>. Ebenfalls in C99 eingeführt wurden Gleitkomma-Datentypen für rein imaginäre Zahlen: <code>float _Imaginary</code>, <code>double _Imaginary</code> und <code>long double _Imaginary</code>.

=== Funktionen ===
Ein C-Programm besteht aus der <code>main</code>-Funktion und optional aus weiteren Funktionen. Weitere Funktionen können entweder selbst definiert werden oder vorgefertigt aus der C-Standard-Bibliothek übernommen werden.

==== main ====
Jedes C-Programm muss eine [[Funktion (Programmierung)|Funktion]] mit dem Namen <code>main</code> haben, anderenfalls wird das Programm nicht kompiliert. Die <code>main</code>-Funktion ist der [[Einsprungpunkt]] eines C-Programms, das heißt die Programmausführung beginnt immer mit dieser Funktion.

<syntaxhighlight lang="c">
// das kürzeste mögliche standardkonforme C89-Programm
main(){return 0;}
</syntaxhighlight>
<syntaxhighlight lang="c">
// das kürzeste mögliche standardkonforme C99-Programm
int main(){}
</syntaxhighlight>
Außer der <code>main</code>-Funktion müssen in einem C-Programm keine weiteren Funktionen enthalten sein. Sollen andere Funktionen ausgeführt werden, müssen sie in der <code>main</code>-Funktion aufgerufen werden. Die <code>main</code>-Funktion wird deshalb auch als Hauptprogramm bezeichnet, alle weiteren Funktionen als [[Unterprogramm]]e.

==== Selbstdefinierte Funktionen ====
In C lassen sich beliebig viele Funktionen selbst definieren. Eine Funktionsdefinition besteht erstens aus dem Datentyp des [[Return Code|Rückgabewerts]], zweitens dem Namen der Funktion, drittens einer eingeklammerten Liste von [[Parameter (Informatik)|Parametern]] und viertens einem eingeklammerten Funktionsrumpf, in welchem ausprogrammiert wird, was die Funktion tun soll.

<syntaxhighlight lang="c">
// Datentyp des Rückgabewerts, Funktionsname und zwei Parameter
int summe(int x, int y) {
// Funktionsrumpf, hier wird die Summe berechnet und zurückgegeben
return x + y;
}

int main() {
// die Funktion wird mit den Werten 2 und 3 aufgerufen, der Rückgabewert
// wird in der Variable „ergebnis“ gespeichert
int ergebnis = summe(2, 3);

// main gibt den Wert von „ergebnis“ zurück
return ergebnis;
}
</syntaxhighlight>

Für die Definition einer Funktion, die nichts zurückgeben soll, verwendet man das Schlüsselwort <code>void</code>. Ebenso falls der Funktion keine Parameter übergeben werden sollen.

<syntaxhighlight lang="c">
#include <stdio.h>

void begruessung() {
puts("Hi!");

return;
}
</syntaxhighlight>

==== Funktionen der C-Standard-Bibliothek ====
Die Funktionen der Standard-Bibliothek sind nicht Teil der Programmiersprache C. Sie werden bei jedem standardkonformen Compiler im hosted environment mitgeliefert und können verwendet werden, sobald man die jeweils entsprechende Header-Datei eingebunden hat. Beispielsweise dient die Funktion <code>printf</code> zur Ausgabe von Text. Sie kann verwendet werden, nachdem man die Header-Datei <code>stdio.h</code> eingebunden hat.

<syntaxhighlight lang="c">
#include <stdio.h>

int main() {
printf("hello world!\n");

return 0;
}
</syntaxhighlight>

=== Anweisungen ===
Eine Funktion besteht aus [[Anweisung (Programmierung)|Anweisungen]]. Wie in den meisten Programmiersprachen sind die wichtigsten Anweisungen: [[Deklaration (Programmierung)|Deklarationen]] und Definitionen, [[Zuweisung]]en, [[Bedingte Anweisung und Verzweigung|bedingte Anweisungen]], Anweisungen die [[Schleife (Programmierung)|Schleifen]] umsetzen sowie Funktionsaufrufe. Im folgenden, eher sinnlosen Programm finden sich Beispiele.

<syntaxhighlight lang="c">
// Unterprogramme
void funktion_die_nichts_tut() { // Definition
return; // Return-Anweisung
}

int plus_eins_funktion(int argument) { // Definition
return argument + 1; // Return-Anweisung
}

// Hauptprogramm
int main() { // Definition
int zahl; // Definition
funktion_die_nichts_tut(); // Funktionsaufruf
zahl = 5; // Zuweisung
zahl = plus_eins_funktion(zahl); // Funktionsaufruf und Zuweisung

if (zahl > 5) // bedingte Anweisung
zahl -= 1; // Zuweisung: der Wert von „zahl“ ist wieder „5“

return 0; // Return-Anweisung
}
</syntaxhighlight>

=== Namensgebung ===
Beim Benennen von eigenen Variablen, Konstanten, Funktionen und Datentypen muss man sich an einige Regeln zur Namensgebung halten. Erstens muss das erste Zeichen eines Bezeichners ein Buchstabe oder Unterstrich sein. Zweitens dürfen die folgenden Zeichen nur die Buchstaben A bis Z und a bis z, Ziffern und der Unterstrich sein. Und drittens darf der Name keines der Schlüsselwörter sein.

Seit C95 sind auch Zeichen aus dem [[Universal Coded Character Set]] in Bezeichnern erlaubt, sofern die Implementierung es unterstützt. Die erlaubten Zeichen sind in Anhang&nbsp;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.

Ab C99 lassen sich diese Zeichen plattformunabhängig über eine [[Escape-Sequenz]] wie folgt ersetzen:
* <code>\uXXXX</code> (wobei X für eine Hexadezimalziffer steht) für Zeichen mit einem Code von 00A0<sub>hex</sub> bis FFFF<sub>hex</sub>.
* <code>\UXXXXXXXX</code> für alle Zeichen mit einem Code ≥00A0<sub>hex</sub>.

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.&nbsp;B. <code>_Complex</code>, <code>_Generic</code>, <code>_Thread_local</code>.

== Standardbibliothek ==
{{Hauptartikel|C-Standard-Bibliothek}}

Die [[C-Standard-Bibliothek]] ist integraler Bestandteil einer ''gehosteten'' ([[Englische Sprache|engl.]] ''{{lang|en|hosted}}'') C-Implementierung. Sie enthält unter anderem [[Makro]]s und [[Funktion (Programmierung)|Funktionen]], die mittels der [[Header-Datei|Standard-Header-Datei]] verfügbar gemacht werden. Auf ''freistehenden'' (englisch ''{{lang|en|freestanding}}'') Implementationen dagegen kann der Umfang der Standardbibliothek eingeschränkt sein.

Die Standardbibliothek ist aufgeteilt in mehrere Standard-Header-Dateien, die [[Linker (Computerprogramm)|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.&nbsp;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.

== Module ==
Eine [[Modul (Software)|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 sogenannten [[Header-Datei]]en. Damit verfügt C über ein schwach ausgeprägtes Modulkonzept.<ref>Scheler, Stilkerich, Schröder-Preikschat: [http://www4.informatik.uni-erlangen.de/Lehre/SS07/V_EZS2/Skript/05_Komponenten.pdf Komponenten/Module.] (PDF; 1,1&nbsp;MB) informatik.uni-erlangen.de</ref><ref name="BMEYER">Bertrand Meyer: ''Objektorientierte Softwareentwicklung''. Hanser, Wien / München; Prentice Hall Internat. 1990, ISBN 3-446-15773-5, S. 406.</ref>

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++]], aber nicht mehr in [[C-Sharp|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 [[Objektcode|Object-Datei]].
Mehrere Object-Dateien können zu einer [[Programmbibliothek|Bibliothek]] zusammengefasst oder einzeln verwendet werden.

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

== Undefiniertes Verhalten ==
{{Hauptartikel|Undefiniertes Verhalten}}
Undefiniertes Verhalten (undefined behavior) ist nach der Definition des C-Standards „Verhalten bei Verwendung eines nicht portablen oder fehlerhaften Programmkonstrukts oder von fehlerhaften Daten, an die diese internationale Norm keine Anforderungen stellt“. Dies kann beispielsweise die Dereferenzierung eines [[Nullwert#Nullwert als grundverschiedener Wert|Nullzeigers]], die Division durch Null, der Zugriff auf Variablen durch Zeiger eines falschen Typs oder ein Überlauf bei vorzeichenbehafteten Ganzzahlen sein.<ref>{{Cite web|url=https://riptutorial.com/c/topic/364/undefined-behavior|title=C language: Undefined behavior |language=en |accessdate=2021-08-25|archiveurl=https://web.archive.org/web/20210523114433/https://riptutorial.com/c/topic/364/undefined-behavior|archivedate=2021-05-23}}</ref>
Unter der Annahme, dass undefiniertes Verhalten in einem korrekten Programm nicht vorkommt, optimieren bestimmte Compiler solche Konstrukte<ref>{{Cite web|url=http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html|title=The LLVM Project Blog: What Every C Programmer Should Know About Undefined Behavior |language=en |accessdate=2021-05-25|archiveurl=https://web.archive.org/web/20110515011136/http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html|archivedate=2011-05-15}}</ref> in einer Weise, die das beobachtbare Verhalten verändern kann, etwa durch Entfernen von Code, der als nicht erreichbar eingestuft wird.

Allgemein kann diese Art der Optimierung dazu führen, dass getestete Programme mit anderen Optimierungsstufen oder neueren Compilerversionen fehlerhaftes Verhalten zeigen. Dieses Compilerverhalten wird teilweise kontrovers diskutiert. Auch kann in der hardwarenahen Programmierung mit C die Verwendung von z.&nbsp;B. Überläufen oder uninitialisierten Variablen zur Laufzeitoptimierung des Codes genutzt werden.<ref>{{Cite web|url=https://www.complang.tuwien.ac.at/kps2015/proceedings/KPS_2015_submission_29.pdf|title=What every compiler writer should know about programmers or “Optimization” based on undefined behaviour hurts performance|last=Ertl|first=Anton|publisher=TU Wien|archiveurl=https://web.archive.org/web/20160304132435/https://www.complang.tuwien.ac.at/kps2015/proceedings/KPS_2015_submission_29.pdf |format=PDF |language=en |archivedate=2016-03-04}}</ref>
Geht der Compiler z.&nbsp;B. bei einer Schleife

<syntaxhighlight lang="c">
for (int i=n; i<n+10; i++)
</syntaxhighlight>
davon aus, dass kein Überlauf auftritt und sie daher höchstens zehnmal durchlaufen wird, kann dies ihn dazu veranlassen, eine vorherige Überprüfung auf Überlauf
<syntaxhighlight lang="c">
if (n < n + 10)
</syntaxhighlight>
als unnötigen Code entfernen. Solche Optimierungen können ihrerseits zu unerwünschtem Verhalten einschließlich registrierter Sicherheitslücken führen (siehe z.&nbsp;B.: [[Common Vulnerabilities and Exposures|CVE]]) führen.<ref>{{Cite web|url=https://cwe.mitre.org/data/definitions/190.html|title=CWE-190: Integer Overflow or Wraparound |language=en |accessdate=2021-08-26|archiveurl=https://web.archive.org/web/20210722145832/https://cwe.mitre.org/data/definitions/190.html|archivedate=2021-07-21}}</ref>

== Compiler ==
Am weitesten verbreitet ist der seit 1987 bestehende [[Freie Software|freie]] C-Compiler der [[GNU Compiler Collection]]. Unter [[Microsoft Windows|Windows]] ist auch der seit 1993 entwickelte Compiler [[Visual C++]] weit verbreitet. Neben diesen beiden stehen zahlreiche weitere Compiler zur Verfügung.

Da es in C vergleichsweise wenige Schlüsselwörter gibt, ergibt sich der Vorteil eines sehr einfachen, kleinen Compilers. Auf neuen Computersystemen ist C deshalb oft die erste verfügbare Programmiersprache (nach [[Maschinensprache|Maschinencode]] und [[Assemblersprache|Assembler]]).

== Beziehung zu Assembler, Portierbarkeit ==
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 (Software)|Portierung]] eines C-Compilers auf eine neue Prozessorplattform ist, verglichen mit anderen Sprachen, wenig aufwendig. Beispielsweise ist der freie [[GNU Compiler Collection|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 [[Plattformunabhängigkeit|Portierbarkeit]] von Programmen, sofern der Programmierer auf [[Integrierter Assembler|Assemblerteile im Quelltext]] und/oder hardwarespezifische C-Konstrukte verzichten kann. In der [[Mikrocontroller]]-Programmierung ist C die mit Abstand am häufigsten verwendete Hochsprache.

== Sicherheit ==
Konzeptionell ist C auf eine einfache Kompilierbarkeit der Quelltexte und für den schnellen Ablauf des Programmcodes ausgelegt. Die [[Compiler]] erzeugen in der Regel aber nur wenig Code zur Gewährleistung der [[Sicherheitslücke|Datensicherheit]] und [[Betriebssicherheit]] während der [[Laufzeit (Informatik)|Laufzeit]] der Programme. Daher wird zunehmend versucht, diese Mängel durch formale [[Verifizierung|Verifikation]] aufzudecken und zu korrigieren beziehungsweise durch zusätzliche vom Programmierer zu erstellende Quelltexte zu beheben.<ref>Junan Qian, Baowen Xu: {{Webarchiv |url=http://www.mii.lt/informatica/pdf/INFO672.pdf |text=Formal Verification for C Program |wayback=20160705102040}} (PDF) In: ''Informatica'', 2007, Volume 18, Number 2, S. 289–304; abgerufen am 5. Juli 2016.</ref><ref>Harvey Tuch: [http://www.nicta.com.au/pub-download/full/2324/ Formal verification of C systems code.] Sydney Research Lab., National ICT Australia, 2009; abgerufen am 5. Juli 2016</ref><ref>Jay Abraham: [http://de.mathworks.com/company/newsletters/articles/improving-software-quality-with-static-code-analysis.html Improving Software Quality with Static Code Analysis.] MathWorks, 2012; abgerufen am 5. Juli 2016</ref>

C schränkt direkte Speicherzugriffe kaum ein. Dadurch kann der Compiler (anders als zum Beispiel in [[Pascal (Programmiersprache)|Pascal]]) nur sehr eingeschränkt bei der Fehlersuche helfen. Aus diesem Grund ist C für sicherheitskritische Anwendungen (Medizintechnik, Verkehrsleittechnik, Raumfahrt) weniger geeignet. Wenn in diesen Bereichen dennoch C eingesetzt wird, so wird in der Regel versucht, die Qualität der erstellten Programme durch zusätzliche Prüfungen wie [[Softwaretest]]s mit hoher [[Testabdeckung]] zu erhöhen.

C enthält einige sicherheitskritische Funktionen; so überschreibt zum Beispiel <code>gets()</code>, in alten Standards eine Funktion der Standardbibliothek, fremde Speicherbereiche ([[Pufferüberlauf#Prozessoren und Programmierstil|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&nbsp;C –&nbsp;die Existenz zahlreicher älterer Quellcodes&nbsp;– 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. <code>gets()</code> wurde mit [[#C11|C11]] endgültig aus der Sprachspezifikation entfernt.<ref>{{Internetquelle |url=https://www.cplusplus.com/reference/cstdio/gets/ |titel=gets – C++ Reference |abruf=2020-03-12}}</ref>

C ist nicht [[Typsicherheit|typsicher]],<ref>Markus Bautsch: ''Cycles of Software Crises – How to avoid insecure and uneconomic software''. In: ''[[ENISA]] Quartely'', Vol. 3, No. 4, Oct–Dec 2007, S. 3–5</ref> da verschiedene [[Datentyp]]en [[Zuweisungskompatibilität|zuweisungskompatibel]] gehandhabt werden können.<ref>Lambert Kenneth Louden: ''Programming Languages: Principles and Practices'', Ch. 8.6.1 ''Type Compatibility'' / 8.7 ''Type Conversion''. Cengage Learning, 2011, ISBN 978-1-133-38749-7.</ref>


== Literatur ==
== Literatur ==
'''Einführungen'''
* [[Brian W. Kernighan]], [[Dennis Ritchie]]: ''Programmieren in C'', Hanser Fachbuch, ISBN 3-446-15497-3
* Helmut Erlenkötter: ''C. Programmieren von Anfang an''. 22. Auflage. Rowohlt, Reinbek bei Hamburg 2015, ISBN 978-3-499-60074-6.
* Joachim Goll: ''C als erste Programmiersprache. Mit den Konzepten von C11''. 8., überarbeitete und erweiterte Auflage. Springer Vieweg, Wiesbaden 2014, ISBN 978-3-8348-1858-4.
* Robert Klima, [[Siegfried Selberherr]]: ''Programmieren in C''. 3. Auflage. Springer, Wien 2010, ISBN 978-3-7091-0392-0.
* Peter Prinz, Ulla Kirch: ''C. Lernen und professionell anwenden''. 3. Auflage. mitp, Heidelberg 2013, ISBN 978-3-8266-9504-9.
* [[Thomas Theis]]: ''Einstieg in C. Für Programmiereinsteiger geeignet''. 3. Auflage. Rheinwerk, Bonn 2020, ISBN 978-3-8362-7569-9.
* Jürgen Wolf, René Krooß: ''Grundkurs C''. 4., aktualisierte und überarbeitete Auflage. Rheinwerk, Bonn 2024, ISBN 978-3-3671-0440-6.

'''Fortgeschritten'''
* Andrew Koenig: ''Der C-Experte: Programmieren ohne Pannen.'' Addison-Wesley, 1989, ISBN 3-89319-233-6 (deutsche Übersetzung von: ''C Traps and Pitfalls.'' Addison-Wesley, 1989.)
* Peter van der Linden: ''Expert-C-Programmierung.'' Verlag Heinz Heise, 1995, ISBN 3-88229-047-1 (deutsche Übersetzung von: ''Expert C Programming.'' Prentice Hall, 1994.)

'''Handbücher'''
* Rolf Isernhagen, Hartmut Helmke: ''Softwaretechnik in C und C++. Das Kompendium. Modulare, objektorientierte und generische Programmierung. ISO-C90, ISO-C99, ISO-C++98, MS-C++.NET''. 4., vollständig überarbeitete Auflage, Hanser, München/Wien 2004, ISBN 3-446-22715-6.
* Jürgen Wolf, René Krooß: ''C von A bis Z. Das umfassende Handbuch''. 5. aktualisierte und erweiterte Auflage, Rheinwerk, Bonn 2023, ISBN 978-3-8362-9504-8.

'''K&R C'''
* Brian Kernighan, Dennis Ritchie: ''The C Programming Language''. Prentice Hall, Englewood Cliffs NJ 1978, ISBN 0-13-110163-3. (Deutsche Übersetzung: Brian Kernighan, Dennis Ritchie: ''Programmieren in C. Mit dem reference manual in deutscher Sprache''. Hanser, München/Wien 1983)


'''K&R2'''
== IRC ==
* Brian Kernighan, Dennis Ritchie: ''The C Programming Language''. 2. Auflage, Prentice Hall, Englewood Cliffs NJ 1988, ISBN 0-13-110362-8. (Deutsche Übersetzung: Brian Kernighan, Dennis Ritchie: ''Programmieren in C. Mit dem C-Reference Manual in deutscher Sprache''. 2. Auflage. Hanser, München/Wien 1990, ISBN 3-446-15497-3)
Einen [[Channel (IRC)|IRC-Channel]], wo man Hilfe bekommen kann, findet man zum Beispiel im [[IRCNet]] in #c (irc://random.ircd.de/C)


== Weblinks ==
== Weblinks ==
{{Commonscat|C (programming language)|C}}
{{Wikibooks1|C Sprachbeschreibung}}
{{Wikibooks1|C-Programmierung}}
{{Wikibooks|C-Programmierung}}
{{Wikibooks|Programmieren in C/C++}}
* [http://eriedel.info/info/c-prog/cpl1.html C-Sprachübersicht (sowie Vergleich mit BASIC).]
* [http://code-reference.com/c Coding Programmer Page / C Library Reference and Examples.] (englisch).
* [https://en.cppreference.com/w/c C Library Reference and Examples (more formal)] (englisch).
* David Straker: [http://syque.com/cstyle/index.htm C Style: Standards and Guidelines.] 1991 erschienenes Buch (englisch).
* Mike Banahan, Declan Brady, Mark Doran: [https://publications.gbdirect.co.uk/c_book/ The C Book.] 1991 (englisch).
* [http://clc-wiki.net/wiki/C_tutorial Einfaches C-Tutorial] für Einsteiger (englisch).


== Einzelnachweise ==
* [http://www.lysator.liu.se/c/ Programming in C]
<references />
* [http://cm.bell-labs.com/cm/cs/who/dmr/primevalC.html Abhandlung über die Urzeiten von C und Compilerversionen von 1972/73 (engl.)]
* [http://faul.dyndns.org/c/ Doku der GLibc, Doku der ANSI-C-Library, Tutorium... (engl.)]


{{Normdaten|TYP=s|LCCN=sh85018532|GND=4113195-2}}
[[Kategorie:Programmiersprache C]]


[[Kategorie:C (Programmiersprache)| ]]
[[ar:سي]]
[[Kategorie:Imperative Programmiersprache]]
[[be:C (мова праграмавання)]]
[[Kategorie:Programmiersprache mit einem ISO-Standard]]
[[bg:C (език за програмиране)]]
[[Kategorie:Unix]]
[[ca:Llenguatge C]]
[[cs:C (programovací jazyk)]]
[[da:C (programmeringssprog)]]
[[en:C programming language]]
[[eo:C (programlingvo)]]
[[es:Lenguaje de programación C]]
[[et:C (programmeerimiskeel)]]
[[eu:C programazio lenguaia]]
[[fi:C-ohjelmointikieli]]
[[fr:C (langage)]]
[[gl:Linguaxe de programación C]]
[[he:C (שפת תכנות)]]
[[hr:C (programski jezik)]]
[[hu:C programozási nyelv]]
[[id:Bahasa pemrograman C]]
[[is:Forritunarmálið C]]
[[it:C (linguaggio)]]
[[ja:C言語]]
[[ko:C 프로그래밍 언어]]
[[lt:C (kalba)]]
[[lv:C (programmēšanas valoda)]]
[[ms:Bahasa pengaturcaraan C]]
[[nl:C (programmeertaal)]]
[[no:C (programmeringsspråk)]]
[[pl:C (język programowania)]]
[[pt:Linguagem de programação C]]
[[ro:Limbajul C]]
[[ru:Си (язык программирования)]]
[[sk:C (programovací jazyk)]]
[[sl:Programski jezik C]]
[[sq:Gjuha programuese C]]
[[sv:C (programspråk)]]
[[th:ภาษาซี]]
[[tr:C programlama dili]]
[[vi:C (ngôn ngữ lập trình)]]
[[zh:C语言]]

Aktuelle Version vom 25. April 2025, 14:35 Uhr

C
Basisdaten
Paradigmen: imperativ, strukturiert
Erscheinungsjahr: 1972
Designer: Dennis Ritchie
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−−, C#, Objective-C, D, Go, Java, JavaScript, PHP, Perl, Python, Vala, Seed7
Betriebssystem: Microsoft Windows, Unix-ähnliches System
www.open-std.org/jtc1/sc22/wg14/

C ist eine imperative und prozedurale Programmiersprache, die der Informatiker Dennis Ritchie in den frühen 1970er Jahren an den Bell Laboratories entwickelte. Seitdem ist sie eine der am weitesten verbreiteten Programmiersprachen.

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, LSL, PHP, Vala oder Perl, orientieren sich an der Syntax und anderen Eigenschaften von C.

Ken Thompson (links) und Dennis Ritchie (rechts)

C wurde 1969–1973 von Dennis Ritchie[2] in den Bell Laboratories für die Programmierung des damals neuen Unix-Betriebssystems entwickelt. Er stützte sich dabei auf die Programmiersprache B, die er und Ken Thompson 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] Ursprünglich war der Name NB („New B“) vorgesehen, daraus wurde schließlich C.[4] Ritchie schrieb auch den ersten Compiler für C. 1973 war die Sprache so weit ausgereift, dass man nun den Unix-Kernel für die PDP-11 neu in C schreiben konnte.

Weitere Entwicklung

[Bearbeiten | Quelltext bearbeiten]

K&R C erweiterte die Sprache um neue Schlüsselwörter wie long oder unsigned und führte die von Mike Lesk entwickelte I/O-Standardbibliothek und auf Empfehlung von Alan Snyder den Präprozessor ein.

C ist eine Programmiersprache, die auf fast allen Computersystemen zur Verfügung steht. Um den Wildwuchs zahlreicher Dialekte einzudämmen, wurde C mehrfach standardisiert (C89/C90, 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 hardwarenahe Programmierung enthalten, in der Regel gut auf andere Zielsysteme portiert werden.

Das Normungsgremium von C ist die ISO/IEC – Arbeitsgruppe JTC1/SC22/WG14 – C, kurz als WG14 bekannt. Die nationalen Standardisierungsorganisationen übernehmen die Veröffentlichungen des internationalen Standards in an ihre Bedürfnisse angepasster Form.

Die 1978 erschienene erste Auflage von The C Programming Language beinhaltet den ehemaligen inoffiziellen Standard K&R C

Bis ins Jahr 1989 gab es keinen offiziellen Standard der Sprache. Seit 1978 galt hingegen das Buch The C Programming Language als informeller De-facto-Standard, welches Brian W. Kernighan und Dennis Ritchie im selben Jahr veröffentlicht hatten.[5] Bezeichnet wird diese Spezifikation als K&R C.

Da in den folgenden Jahren die Zahl an Erweiterungen der Sprache ständig wuchs, man sich nicht auf eine gemeinsame Standard-Bibliothek einigen konnte und nicht einmal die UNIX-Compiler K&R C vollständig implementierten, wurde beschlossen, einen offiziellen Standard festzulegen. Nachdem dieser schließlich im Jahr 1989 erschienen war, blieb K&R C zwar noch für einige Jahre De-facto-Standard vieler Programmierer, verlor dann aber rasch an Bedeutung.

Im Jahr 1983 setzte das American National Standards Institute (ANSI) ein Komitee namens X3J11 ein, das 1989 seine Arbeit abschloss und die Norm ANSI X3.159-1989 Programming Language C verabschiedete. Diese Version der Sprache C wird auch kurz als ANSI C, Standard C oder C89 bezeichnet.

Ein Jahr später übernahm die International Organization for Standardization (ISO) den bis dahin rein amerikanischen Standard auch als internationale Norm, die ISO/IEC 9899:1990, kurz auch als C90 bezeichnet. Die Namen C89 und C90 beziehen sich also auf dieselbe Version von C.

Nach der ersten Entwicklung durch ANSI und ISO wurde der Sprachstandard für einige Jahre kaum geändert. Erst 1995 erschien das Normative Amendment 1 zu C90. Es hieß ISO/IEC 9899/AMD1:1995 und wird auch kurz als C95 bezeichnet. Neben der Korrektur einiger Details wurden mit C95 internationale Schriftsätze besser unterstützt.

Nach einigen kleineren Revisionen erschien im Jahr 1999 der neue Standard ISO/IEC 9899:1999, kurz C99. Er war größtenteils mit C90 kompatibel und führte einige neue, teilweise von C++ übernommene Features ein, von denen einige bereits zuvor von verschiedenen Compilern implementiert worden waren. C99 wurde im Lauf der Jahre durch drei Technical Corrigendas ergänzt.

Im Jahr 2007 begann die Entwicklung eines neuen Standards mit dem inoffiziellen Arbeitstitel C1X. Er wurde im Dezember 2011 veröffentlicht und ist in der Kurzform als C11 bekannt. Neben einer besseren Kompatibilität mit C++ wurden der Sprache wiederum neue Features hinzugefügt.[6][7]

Diese Norm entspricht der von C11 mit der Ausnahme von Fehlerkorrekturen und einem neuen Wert von __STDC_VERSION__ und wird daher im selben Umfang wie C11 unterstützt.[8] Der Standard wurde im Juni 2018 unter der Norm ISO/IEC 9899:2018 freigegeben.[9]

The C Programming Language

Trotz des eher hohen Alters ist die Sprache C auch heute weit verbreitet und wird sowohl im Hochschulbereich als auch in der Industrie und im Open-Source-Bereich verwendet.[10]

System- und Anwendungsprogrammierung

[Bearbeiten | Quelltext bearbeiten]

Das Haupteinsatzgebiet von C liegt in der Systemprogrammierung, insbesondere von eingebetteten Systemen, Treibern und Betriebssystemkernen. 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 eine Laufzeitumgebung zu haben.

Auch Anwendungssoftware wird oft in C erstellt, wobei die Relevanz der Sprache hier hinter andere zurückfiel, das ist besonders deutlich auf mobilen Plattformen. Viele Programmierschnittstellen für Anwendungsprogramme und Betriebssystem-APIs werden in Form von C-Schnittstellen implementiert, zum Beispiel Win32.[11]

Implementierung anderer Sprachen

[Bearbeiten | Quelltext bearbeiten]

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 verwendet, um ohne maschinenspezifische Entwicklung für den Codegenerator die Portabilität zu erhöhen (C-Compiler existieren für nahezu jede Plattform). 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 (englisch bindings) 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).

C ist case-sensitiv.

Außerdem besitzt C 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 Funktionen der C-Standard-Bibliothek realisiert werden (zum Beispiel die Ein- und Ausgabe über Konsole oder Dateien, dynamische Speicherverwaltung usw.).

In C89 gibt es 32 Schlüsselwörter:

auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while

Mit C99 kamen fünf weitere dazu:

_Bool
_Complex
_Imaginary
inline
restrict

Mit C11 kamen sieben weitere hinzu:

_Alignas
_Alignof
_Atomic
_Generic
_Noreturn
_Static_assert
_Thread_local

Hallo-Welt-Programm

[Bearbeiten | Quelltext bearbeiten]

Eine einfache Version des Hallo-Welt-Programms in C ist diejenige, die Ritchie und Kernighan selbst in der zweiten Auflage ihres Buches The C Programming Language verwendet haben.[12] Zu beachten ist, dass im älteren ANSI C Standard kein Rückgabetyp angegeben werden muss, da der Compiler von einem impliziten int als Rückgabetyp ausgeht.

#include <stdio.h>
main()
{
  printf("hello, world\n");
}

Zum Speichern eines Zeichens (sowie von kleinen Zahlen) verwendet man in C üblicherweise den Datentyp Character, geschrieben als char.

Vom Computer tatsächlich gespeichert wird nicht das Zeichen (wie zum Beispiel „A“), sondern eine gleichbedeutende mindestens acht Bit lange Binärzahl (z. B. 01000001). Diese Binärzahl steht im Speicher und kann anhand einer Tabelle jederzeit automatisch in den entsprechenden Buchstaben umgewandelt werden, wobei der aktuelle Zeichensatz bzw. die Codepage der Systemumgebung entscheidend ist. Zum Beispiel steht 01000001 gemäß der ASCII-Tabelle für das Zeichen „A“.

Um auch Zeichen aus Zeichensätzen aufnehmen zu können, die mehr Zeichen umfassen als der relativ kleine ASCII-Zeichensatz, wurde mit wchar_t bald ein zweiter für Zeichen konzipierter Datentyp eingeführt.

// gespeichert wird nicht das Zeichen „A“, sondern meist ein Byte ("01000001")
char zeichen = 'A';

// gibt das Zeichen mit der Ordnungszahl 65 aus (in ASCII ein „A“)
printf("%c", 65);

Zum Speichern einer Ganzzahl (wie zum Beispiel 3) verwendet man eine Variable vom Datentyp Integer, geschrieben als int. Die Größe eines Integers beträgt heutzutage (je nach Prozessorarchitektur und Betriebssystem) meist 32 Bit, manchmal noch 16 Bit und fast nie 64 Bit. In 16 Bit lassen sich 65536 verschiedene Werte speichern. Um die Verwendung von negativen Zahlen zu ermöglichen, reicht der Wertebereich bei 16 Bit gewöhnlich von -32768 bis 32767. Werden keine negativen Zahlen benötigt, kann der Programmierer mit unsigned int aber einen vorzeichenlosen Integer verwenden. Bei 16 Bit großen Integern ergibt das einen Wertebereich von 0 bis 65535.

Um den Wertebereich eines Integers zu verkleinern oder zu vergrößern, stellt man ihm einen der Qualifizierer short, long oder long long voran. Das Schlüsselwort int kann dann auch weggelassen werden, so ist long gleichbedeutend mit long int. Um zwischen vorzeichenbehafteten und vorzeichenlosen Ganzzahlen zu wechseln, gibt es die beiden Qualifizierer signed und unsigned. Für einen vorzeichenbehafteten Integer kann der Qualifizierer aber auch weggelassen werden, so ist signed int gleichbedeutend mit int. 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. Obwohl der Datentyp char für Textzeichen vorgesehen ist, können dessen Werte auch als ganze Zahlen mit einem Wertebereich von 0 bis 255 (unsigned) oder von -128 bis +127 (signed) verwendet werden.

char ganzzahl = 1;      // mindestens 8 Bit, also 256 mögliche Werte
short ganzzahl = 2;     // mindestens 16 Bit, also 65536 mögliche Werte
int ganzzahl = 3;       // mindestens 16 Bit, also 65536 mögliche Werte
long ganzzahl = 4;      // mindestens 32 Bit, also 4294967296 mögliche Werte
long long ganzzahl = 5; // mindestens 64 Bit, also 18446744073709551616 mögliche Werte

float und double

[Bearbeiten | Quelltext bearbeiten]

Zahlen mit Nachkommastellen werden in einem der drei Datentypen float, double und long double gespeichert. In den meisten C-Implementierungen entsprechen die Datentypen float und double dem international gültigen Standard für binäre Gleitpunktarithmetiken (IEC 559, im Jahr 1989 aus dem älteren amerikanischen Standard IEEE 754 hervorgegangen). Ein float implementiert das „einfach lange Format“, ein double das „doppelt lange Format“. Dabei umfasst ein float 32 Bit, ein double 64 Bit. doubles sind also genauer. Floats werden aufgrund dieses Umstands nur noch in speziellen Fällen verwendet. Die Größe von long doubles ist je nach Implementierung unterschiedlich, ein long double darf aber auf keinen Fall kleiner sein als ein double. Die genauen Eigenschaften und Wertebereiche auf der benutzten Architektur können über die Header-Datei <float.h> ermittelt werden.

// Genauigkeit ist jeweils implementierungsabhängig

float kommazahl = 0.000001f;
double kommazahl = 0.000000000000002;
long double kommazahl = 0.3l;

Der Datentyp void wird im C-Standard als „unvollständiger Typ“ bezeichnet. Man kann keine Variablen von diesem Typ erzeugen. Verwendet wird void erstens, wenn eine Funktion keinen Wert zurückgeben soll, zweitens wenn explizit eine leere Parameterliste für eine Funktion verlangt wird und drittens, wenn ein Zeiger auf „Objekte beliebigen Typs“ zeigen soll.

// Deklaration einer Funktion, die keinen Wert zurückgibt
void funktionsname();

// Deklaration einer Funktion, die int zurückgibt und keine Parameter akzeptiert
int funktionsname(void);

// Zeiger auf ein Objekt von beliebigem Typ
void* zeigername;

Wie in anderen Programmiersprachen sind Zeiger in C Variablen, die statt eines direkt verwendbaren Wertes (wie das Zeichen „A“ oder die Zahl 5) eine Speicheradresse (wie etwa die Adresse 170234) speichern. Die Adressen im Speicher sind durchnummeriert. An der Speicheradresse 170234 könnte zum Beispiel der Wert 00000001 gespeichert sein (Binärwert der Dezimalzahl 1). Zeiger ermöglichen es, auf den Wert zuzugreifen, der an einer Speicheradresse liegt. Dieser Wert kann wiederum eine Adresse sein, die auf eine weitere Speicheradresse zeigt. Bei der Deklaration eines Zeigers wird zuerst der Datentyp des Objekts angegeben, auf das gezeigt wird, danach ein Asterisk, danach der gewünschte Name des Zeigers.

char* zeiger;   // kann die Adresse eines Characters speichern
double* zeiger; // kann die Adresse eines Doubles speichern

Wie in anderen Programmiersprachen verwendet man in C Arrays, um mehrere Werte desselben Datentyps zu speichern. Die Werte eines Arrays haben aufeinanderfolgende Speicheradressen. Die Anzahl der verschiedenen Werte eines Arrays ist als Index des Feldes festgelegt. Da es in C keinen eigenen Datentyp für Strings gibt, werden Arrays auch verwendet, um Zeichenfolgen zu speichern.

// Definition eines Arrays mit 3 ganzzahligen Werten
int zahlen[] = { 17, 0, 3 };

// Array, das zur Speicherung eines Strings verwendet wird
char string[] = "Hallo, Welt!\n";

Um verschiedenartige Daten in einer Variable zu speichern, verwendet man Structures, geschrieben als struct. Auf diese Weise können Variablen verschiedenen Datentyps zusammengefasst werden.

struct person {
    char* vorname;
    char nachname[20];
    int alter;
    double groesse;
};

Wie in anderen Programmiersprachen dient ein Enum in C dazu, mehrere konstante Werte zu einem Typ zu kombinieren.

enum Temperatur { WARM, KALT, MITTEL };

enum Temperatur heutige_temperatur = WARM;

if (heutige_temperatur == KALT)
    printf("Warm anziehen!"); // wird nicht ausgegeben, da es heute „WARM“ ist

Das Schlüsselwort typedef wird zur Erstellung eines Alias für einen Datentyp verwendet.

// legt den Alias "Ganzzahl" für den Datentyp "int" an
typedef int Ganzzahl;

// ist jetzt gleichbedeutend zu: int a, b;
Ganzzahl a, b;

Bis zum C99-Standard gab es keinen Datentyp zum Speichern eines Wahrheitswerts. Erst seit 1999 können Variablen als _Bool deklariert werden und einen der beiden Werte 0 (falsch) oder 1 (wahr) aufnehmen.

_Bool a = 1; // seit C99

Durch explizite Verwendung der Header-Datei stdbool.h ist die verbreitete Verwendung des logischen Datentyps bool mit den zwei möglichen Ausprägungen true bzw. false möglich:

#include <stdbool.h>

bool a = true; // seit C99

_Complex und _Imaginary

[Bearbeiten | Quelltext bearbeiten]

Seit C99 gibt es 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.

Ein C-Programm besteht aus der main-Funktion und optional aus weiteren Funktionen. Weitere Funktionen können entweder selbst definiert werden oder vorgefertigt aus der C-Standard-Bibliothek übernommen werden.

Jedes C-Programm muss eine Funktion mit dem Namen main haben, anderenfalls wird das Programm nicht kompiliert. Die main-Funktion ist der Einsprungpunkt eines C-Programms, das heißt die Programmausführung beginnt immer mit dieser Funktion.

// das kürzeste mögliche standardkonforme C89-Programm
main(){return 0;}
// das kürzeste mögliche standardkonforme C99-Programm
int main(){}

Außer der main-Funktion müssen in einem C-Programm keine weiteren Funktionen enthalten sein. Sollen andere Funktionen ausgeführt werden, müssen sie in der main-Funktion aufgerufen werden. Die main-Funktion wird deshalb auch als Hauptprogramm bezeichnet, alle weiteren Funktionen als Unterprogramme.

Selbstdefinierte Funktionen

[Bearbeiten | Quelltext bearbeiten]

In C lassen sich beliebig viele Funktionen selbst definieren. Eine Funktionsdefinition besteht erstens aus dem Datentyp des Rückgabewerts, zweitens dem Namen der Funktion, drittens einer eingeklammerten Liste von Parametern und viertens einem eingeklammerten Funktionsrumpf, in welchem ausprogrammiert wird, was die Funktion tun soll.

// Datentyp des Rückgabewerts, Funktionsname und zwei Parameter
int summe(int x, int y) {
    // Funktionsrumpf, hier wird die Summe berechnet und zurückgegeben
    return x + y;
}

int main() {
    // die Funktion wird mit den Werten 2 und 3 aufgerufen, der Rückgabewert
    // wird in der Variable „ergebnis“ gespeichert
    int ergebnis = summe(2, 3);

    // main gibt den Wert von „ergebnis“ zurück
    return ergebnis;
}

Für die Definition einer Funktion, die nichts zurückgeben soll, verwendet man das Schlüsselwort void. Ebenso falls der Funktion keine Parameter übergeben werden sollen.

#include <stdio.h>

void begruessung() {
    puts("Hi!");

    return;
}

Funktionen der C-Standard-Bibliothek

[Bearbeiten | Quelltext bearbeiten]

Die Funktionen der Standard-Bibliothek sind nicht Teil der Programmiersprache C. Sie werden bei jedem standardkonformen Compiler im hosted environment mitgeliefert und können verwendet werden, sobald man die jeweils entsprechende Header-Datei eingebunden hat. Beispielsweise dient die Funktion printf zur Ausgabe von Text. Sie kann verwendet werden, nachdem man die Header-Datei stdio.h eingebunden hat.

#include <stdio.h>

int main() {
    printf("hello world!\n");

    return 0;
}

Eine Funktion besteht aus Anweisungen. Wie in den meisten Programmiersprachen sind die wichtigsten Anweisungen: Deklarationen und Definitionen, Zuweisungen, bedingte Anweisungen, Anweisungen die Schleifen umsetzen sowie Funktionsaufrufe. Im folgenden, eher sinnlosen Programm finden sich Beispiele.

// Unterprogramme
void funktion_die_nichts_tut() { // Definition
    return;                      // Return-Anweisung
}

int plus_eins_funktion(int argument) { // Definition
    return argument + 1;               // Return-Anweisung
}

// Hauptprogramm
int main() {                         // Definition
    int zahl;                        // Definition
    funktion_die_nichts_tut();       // Funktionsaufruf
    zahl = 5;                        // Zuweisung
    zahl = plus_eins_funktion(zahl); // Funktionsaufruf und Zuweisung

    if (zahl > 5)  // bedingte Anweisung
        zahl -= 1; // Zuweisung: der Wert von „zahl“ ist wieder „5“

    return 0; // Return-Anweisung
}

Beim Benennen von eigenen Variablen, Konstanten, Funktionen und Datentypen muss man sich an einige Regeln zur Namensgebung halten. Erstens muss das erste Zeichen eines Bezeichners ein Buchstabe oder Unterstrich sein. Zweitens dürfen die folgenden Zeichen nur die Buchstaben A bis Z und a bis z, Ziffern und der Unterstrich sein. Und drittens darf der Name keines der Schlüsselwörter sein.

Seit C95 sind auch Zeichen aus dem Universal Coded 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.

Ab C99 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.

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. _Complex, _Generic, _Thread_local.

Standardbibliothek

[Bearbeiten | Quelltext bearbeiten]

Die C-Standard-Bibliothek ist integraler Bestandteil einer gehosteten (engl. hosted) C-Implementierung. Sie enthält unter anderem Makros und Funktionen, die mittels der Standard-Header-Datei verfügbar gemacht werden. Auf freistehenden (englisch 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.

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 sogenannten Header-Dateien. Damit verfügt C über ein schwach ausgeprägtes Modulkonzept.[13][14]

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++, aber nicht mehr in 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 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.

Undefiniertes Verhalten

[Bearbeiten | Quelltext bearbeiten]

Undefiniertes Verhalten (undefined behavior) ist nach der Definition des C-Standards „Verhalten bei Verwendung eines nicht portablen oder fehlerhaften Programmkonstrukts oder von fehlerhaften Daten, an die diese internationale Norm keine Anforderungen stellt“. Dies kann beispielsweise die Dereferenzierung eines Nullzeigers, die Division durch Null, der Zugriff auf Variablen durch Zeiger eines falschen Typs oder ein Überlauf bei vorzeichenbehafteten Ganzzahlen sein.[15] Unter der Annahme, dass undefiniertes Verhalten in einem korrekten Programm nicht vorkommt, optimieren bestimmte Compiler solche Konstrukte[16] in einer Weise, die das beobachtbare Verhalten verändern kann, etwa durch Entfernen von Code, der als nicht erreichbar eingestuft wird.

Allgemein kann diese Art der Optimierung dazu führen, dass getestete Programme mit anderen Optimierungsstufen oder neueren Compilerversionen fehlerhaftes Verhalten zeigen. Dieses Compilerverhalten wird teilweise kontrovers diskutiert. Auch kann in der hardwarenahen Programmierung mit C die Verwendung von z. B. Überläufen oder uninitialisierten Variablen zur Laufzeitoptimierung des Codes genutzt werden.[17] Geht der Compiler z. B. bei einer Schleife

  for (int i=n; i<n+10; i++)

davon aus, dass kein Überlauf auftritt und sie daher höchstens zehnmal durchlaufen wird, kann dies ihn dazu veranlassen, eine vorherige Überprüfung auf Überlauf

  if (n < n + 10)

als unnötigen Code entfernen. Solche Optimierungen können ihrerseits zu unerwünschtem Verhalten einschließlich registrierter Sicherheitslücken führen (siehe z. B.: CVE) führen.[18]

Am weitesten verbreitet ist der seit 1987 bestehende freie C-Compiler der GNU Compiler Collection. Unter Windows ist auch der seit 1993 entwickelte Compiler Visual C++ weit verbreitet. Neben diesen beiden stehen zahlreiche weitere Compiler zur Verfügung.

Da es in C vergleichsweise wenige Schlüsselwörter gibt, ergibt sich der Vorteil eines sehr einfachen, kleinen Compilers. Auf neuen Computersystemen ist C deshalb oft die erste verfügbare Programmiersprache (nach Maschinencode und Assembler).

Beziehung zu Assembler, Portierbarkeit

[Bearbeiten | Quelltext bearbeiten]

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 aufwendig. Beispielsweise 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.

Konzeptionell ist C auf eine einfache Kompilierbarkeit der Quelltexte und für den schnellen Ablauf des Programmcodes ausgelegt. Die Compiler erzeugen in der Regel aber nur wenig Code zur Gewährleistung der Datensicherheit und Betriebssicherheit während der Laufzeit der Programme. Daher wird zunehmend versucht, diese Mängel durch formale Verifikation aufzudecken und zu korrigieren beziehungsweise durch zusätzliche vom Programmierer zu erstellende Quelltexte zu beheben.[19][20][21]

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. Wenn in diesen Bereichen dennoch C eingesetzt wird, so wird in der Regel versucht, die Qualität der erstellten Programme durch zusätzliche Prüfungen wie Softwaretests mit hoher Testabdeckung zu erhöhen.

C enthält einige sicherheitskritische Funktionen; so überschreibt zum Beispiel gets(), in alten Standards 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. gets() wurde mit C11 endgültig aus der Sprachspezifikation entfernt.[22]

C ist nicht typsicher,[23] da verschiedene Datentypen zuweisungskompatibel gehandhabt werden können.[24]

Einführungen

Fortgeschritten

  • Andrew Koenig: Der C-Experte: Programmieren ohne Pannen. Addison-Wesley, 1989, ISBN 3-89319-233-6 (deutsche Übersetzung von: C Traps and Pitfalls. Addison-Wesley, 1989.)
  • Peter van der Linden: Expert-C-Programmierung. Verlag Heinz Heise, 1995, ISBN 3-88229-047-1 (deutsche Übersetzung von: Expert C Programming. Prentice Hall, 1994.)

Handbücher

  • Rolf Isernhagen, Hartmut Helmke: Softwaretechnik in C und C++. Das Kompendium. Modulare, objektorientierte und generische Programmierung. ISO-C90, ISO-C99, ISO-C++98, MS-C++.NET. 4., vollständig überarbeitete Auflage, Hanser, München/Wien 2004, ISBN 3-446-22715-6.
  • Jürgen Wolf, René Krooß: C von A bis Z. Das umfassende Handbuch. 5. aktualisierte und erweiterte Auflage, Rheinwerk, Bonn 2023, ISBN 978-3-8362-9504-8.

K&R C

  • Brian Kernighan, Dennis Ritchie: The C Programming Language. Prentice Hall, Englewood Cliffs NJ 1978, ISBN 0-13-110163-3. (Deutsche Übersetzung: Brian Kernighan, Dennis Ritchie: Programmieren in C. Mit dem reference manual in deutscher Sprache. Hanser, München/Wien 1983)

K&R2

  • Brian Kernighan, Dennis Ritchie: The C Programming Language. 2. Auflage, Prentice Hall, Englewood Cliffs NJ 1988, ISBN 0-13-110362-8. (Deutsche Übersetzung: Brian Kernighan, Dennis Ritchie: Programmieren in C. Mit dem C-Reference Manual in deutscher Sprache. 2. Auflage. Hanser, München/Wien 1990, ISBN 3-446-15497-3)
Commons: C – Sammlung von Bildern, Videos und Audiodateien
Wikibooks: C-Programmierung – Lern- und Lehrmaterialien
Wikibooks: Programmieren in C/C++ – Lern- und Lehrmaterialien

Einzelnachweise

[Bearbeiten | Quelltext bearbeiten]
  1. Dennis M. Ritchie: The Development of the C Language. Lucent Technologies, Januar 1993, abgerufen am 10. September 2015: „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. Dennis M. Ritchie: The Development of the C Language. Lucent Technologies, Januar 1993, abgerufen am 10. September 2015.
  3. Ken Thompson: Users’ Reference to B. Abgerufen am 30. Mai 2015.
  4. Die Unix-Story. Geschichtliches Sachbuch über das Computerbetriebssystem Unix von Autor Brian W. Kernighan, 254 Seiten, Oktober 2020, dpunkt.verlag GmbH, Heidelberg, S. 97
  5. Brian W. Kernighan, Dennis M. Ritchie: The C Programming Language, Prentice Hall, Englewood Cliffs (NJ) 1978, ISBN 0-13-110163-3.
  6. Sprachdefinition von C11 als ISO-Standard ISO/IEC 9899:2011, veröffentlicht am 8. Dezember 2011.
  7. ISO aktualisiert C-Standard, Artikel auf heise online, vom 22. Dezember 2011.
  8. Options Controlling C Dialect. Abgerufen am 8. September 2018.
  9. ISO/IEC 9899:2018 Programming languages C. Abgerufen am 8. September 2018.
  10. Rolf Isernhagen, Hartmut Helmke: Softwaretechnik in C und C++. Das Kompendium. Modulare, objektorientierte und generische Programmierung. ISO-C90, ISO-C99, ISO-C++98, MS-C++.NET. 4., vollständig überarbeitete Auflage, Hanser, München/Wien 2004, ISBN 3-446-22715-6, Seite 4.
  11. Walkthrough: Creating Windows Desktop Applications (C++) Microsoft Docs, abgerufen am 5. Dezember 2019.
  12. Brian Kernighan, Dennis Ritchie: The C Programming Language. 2. Auflage, Prentice Hall, Englewood Cliffs (NJ) 1988, ISBN 0-13-110362-8, Seite 6.
  13. Scheler, Stilkerich, Schröder-Preikschat: Komponenten/Module. (PDF; 1,1 MB) informatik.uni-erlangen.de
  14. Bertrand Meyer: Objektorientierte Softwareentwicklung. Hanser, Wien / München; Prentice Hall Internat. 1990, ISBN 3-446-15773-5, S. 406.
  15. C language: Undefined behavior. Archiviert vom Original am 23. Mai 2021; abgerufen am 25. August 2021 (englisch).
  16. The LLVM Project Blog: What Every C Programmer Should Know About Undefined Behavior. Archiviert vom Original am 15. Mai 2011; abgerufen am 25. Mai 2021 (englisch).
  17. Anton Ertl: What every compiler writer should know about programmers or “Optimization” based on undefined behaviour hurts performance. (PDF) TU Wien, archiviert vom Original am 4. März 2016; (englisch).
  18. CWE-190: Integer Overflow or Wraparound. Archiviert vom Original am 21. Juli 2021; abgerufen am 26. August 2021 (englisch).
  19. Junan Qian, Baowen Xu: Formal Verification for C Program (Memento vom 5. Juli 2016 im Internet Archive) (PDF) In: Informatica, 2007, Volume 18, Number 2, S. 289–304; abgerufen am 5. Juli 2016.
  20. Harvey Tuch: Formal verification of C systems code. Sydney Research Lab., National ICT Australia, 2009; abgerufen am 5. Juli 2016
  21. Jay Abraham: Improving Software Quality with Static Code Analysis. MathWorks, 2012; abgerufen am 5. Juli 2016
  22. gets – C++ Reference. Abgerufen am 12. März 2020.
  23. Markus Bautsch: Cycles of Software Crises – How to avoid insecure and uneconomic software. In: ENISA Quartely, Vol. 3, No. 4, Oct–Dec 2007, S. 3–5
  24. Lambert Kenneth Louden: Programming Languages: Principles and Practices, Ch. 8.6.1 Type Compatibility / 8.7 Type Conversion. Cengage Learning, 2011, ISBN 978-1-133-38749-7.