Wikipedia · einfach zusammengefasst · Stand
C (Programmiersprache)
C ist eine imperative und prozedurale Programmiersprache, die der Informatiker Dennis Ritchie in den frühen 1970er Jahren an den Bell Laboratories entwickelte.
Inhalt6 Abschnitte
Grundidee und Bedeutung
C ist eine imperative und prozedurale Programmiersprache. „Imperativ“ bedeutet, dass ein Programm aus Anweisungen besteht, die Schritt für Schritt ausgeführt werden; „prozedural“ bedeutet, dass Programme stark über Funktionen gegliedert werden. C wurde 1972 von Dennis Ritchie an den Bell Laboratories entwickelt und gehört seitdem zu den am weitesten verbreiteten Programmiersprachen.
C ist besonders wichtig, weil sie nahe an der Hardware arbeiten kann und trotzdem portabler ist als Assembler. Viele grundlegende Programme von Unix-Systemen und die Systemkernel vieler Betriebssysteme sind in C geschrieben. Auch viele spätere Sprachen, darunter C++, Objective-C, C#, D, Java, JavaScript, PHP, Perl und Python, orientieren sich an Syntax oder Eigenschaften von C.
Entwicklung und Standards
C entstand 1969-1973 aus der Sprache B, die Dennis Ritchie und Ken Thompson 1969/1970 geschrieben hatten. B geht wiederum auf BCPL von Martin Richards zurück. 1973 war C so weit ausgereift, dass der Unix-Kernel für die PDP-11 neu in C geschrieben werden konnte.
Vor 1989 gab es keinen offiziellen Standard. Das 1978 erschienene Buch The C Programming Language von Brian W. Kernighan und Dennis Ritchie galt als informeller De-facto-Standard; diese Form heißt K&R C. 1989 verabschiedete ANSI die Norm ANSI X3.159-1989, auch ANSI C oder C89 genannt. 1990 übernahm die ISO diese Fassung als ISO/IEC 9899:1990, kurz C90. C89 und C90 bezeichnen also dieselbe Sprachversion.
Weitere wichtige Standards sind C99 nach ISO/IEC 9899:1999, C11 nach ISO/IEC 9899:2011, C18 nach ISO/IEC 9899:2018 und C23 nach ISO/IEC 9899:2024. C18 entspricht im Wesentlichen C11 mit Fehlerkorrekturen und einem neuen Wert von STDC_VERSION. C23 wurde am 31. Oktober 2024 veröffentlicht und enthält umfangreiche Erweiterungen. Seit Januar 2024 wird unter dem Namen C2Y an einer weiteren Version gearbeitet.
Einsatzgebiete und Portabilität
C wird im Hochschulbereich, in der Industrie und im Open-Source-Bereich verwendet. Das Haupteinsatzgebiet ist die Systemprogrammierung, besonders bei eingebetteten Systemen, Treibern und Betriebssystemkernen. Der Grund ist die Kombination aus Effizienz, Portabilität, direktem Hardwarezugriff und geringen Anforderungen an eine Laufzeitumgebung.
Auch Anwendungssoftware kann in C geschrieben werden, allerdings ist C dort weniger dominant als früher, besonders auf mobilen Plattformen. Viele Programmierschnittstellen und Betriebssystem-APIs besitzen C-Schnittstellen, zum Beispiel Win32.
C wird außerdem zur Implementierung anderer Sprachen genutzt. Wegen hoher Ausführungsgeschwindigkeit und geringer Codegröße werden Compiler, Programmbibliotheken und Interpreter höherer Programmiersprachen oft in C geschrieben, zum Beispiel Teile der Java Virtual Machine. Manche Sprachimplementierungen übersetzen zuerst in C-Code, der dann kompiliert wird, um Portabilität zu erreichen. Außerdem wird C häufig für bindings verwendet, also Anbindungen, durch die Programme anderer Sprachen C-Funktionen aufrufen können.
C wurde als Abstraktion zu Assembler entworfen. C-Code kann sehr hardwarenah formuliert werden, oft mit direkter Zuordnung zu wenigen Maschineninstruktionen. Weil C-Compiler für viele Prozessoren und Betriebssysteme existieren, können Programme oft auf andere Systeme übertragen werden, solange sie keine Assemblerteile oder hardwarespezifischen C-Konstrukte verwenden.
Sprache, Datentypen und Programmaufbau
C ist case-sensitiv, unterscheidet also Groß- und Kleinschreibung. Die Sprache hat vergleichsweise wenige Schlüsselwörter: In C89 sind es 32, mit C99 kamen fünf hinzu (_Bool, _Complex, _Imaginary, inline, restrict), mit C11 sieben weitere (_Alignas, _Alignof, _Atomic, _Generic, _Noreturn, _Static_assert, _Thread_local). Viele Aufgaben, die andere Sprachen mit eigenen Schlüsselwörtern lösen, werden in C über Funktionen der Standardbibliothek erledigt.
Wichtige Datentypen sind char für Zeichen und kleine Zahlen, int für Ganzzahlen, float, double und long double für Gleitkommazahlen, also Zahlen mit Nachkommastellen. Ein int hat heute meist 32 Bit, manchmal 16 Bit und fast nie 64 Bit; bei 16 Bit umfasst ein vorzeichenbehafteter int gewöhnlich −32768 bis 32767, ein unsigned int 0 bis 65535. float entspricht meist dem 32-Bit-Format, double dem 64-Bit-Format nach IEC 559 beziehungsweise IEEE 754. void ist ein unvollständiger Typ und wird unter anderem verwendet, wenn Funktionen keinen Wert zurückgeben oder wenn ein Zeiger auf Objekte beliebigen Typs zeigen soll.
Zeiger sind Variablen, die Speicheradressen speichern. Sie ermöglichen direkten Zugriff auf Werte im Speicher und sind ein zentrales, aber fehleranfälliges Merkmal von C. Felder, also Arrays, speichern mehrere Werte desselben Datentyps an aufeinanderfolgenden Speicheradressen. Da C keinen eigenen Datentyp für Strings besitzt, werden Zeichenfolgen als char-Arrays gespeichert.
Mit struct lassen sich mehrere Variablen verschiedener Datentypen zu einer Struktur zusammenfassen. enum dient dazu, mehrere konstante Werte zu einem Typ zu kombinieren. typedef erstellt einen Alias für einen Datentyp. Seit C99 gibt es _Bool für Wahrheitswerte 0 (falsch) und 1 (wahr); über stdbool.h können bool, true und false verwendet werden. Ebenfalls seit C99 gibt es _Complex für komplexe Zahlen und _Imaginary für rein imaginäre Zahlen.
Ein C-Programm besteht aus Funktionen. Für Konsolenprogramme wird meist eine Funktion main als Einsprungpunkt verwendet, obwohl dies eher mit dem Start-Code und dem Linker zusammenhängt als mit der Sprache C allein. Weitere Funktionen können selbst definiert oder aus der C-Standard-Bibliothek übernommen werden. Eine Funktion besteht aus Rückgabetyp, Funktionsname, Parameterliste und Funktionsrumpf. In Funktionen stehen Anweisungen wie Deklarationen, Definitionen, Zuweisungen, Bedingungen, Schleifen und Funktionsaufrufe.
Bibliothek, Module und Übersetzung
Die C-Standard-Bibliothek gehört zu einer gehosteten C-Implementierung. „Gehostet“ bedeutet, dass Compiler und Programm in einer Betriebssystemumgebung mit Diensten wie Dateisystem, Ein- und Ausgabe und Speichermanagement laufen. In freistehenden Implementierungen, etwa ohne Betriebssystem, kann der Umfang der Standardbibliothek eingeschränkt sein. Die Bibliothek stellt Makros und Funktionen über Standard-Header-Dateien bereit, zum Beispiel stdio.h für printf.
C modularisiert Programme auf Dateiebene. Eine Datei bildet eine Übersetzungseinheit. Üblicherweise besitzt ein Modul eine Quellcodedatei mit der Endung .c und eine Header-Datei mit der Endung .h. Die .c-Datei enthält vor allem die Implementierung, die .h-Datei die nach außen sichtbare Schnittstelle. Es ist Aufgabe des Programmierers, beide konsistent zu halten. Jedes Modul kann einzeln übersetzt werden und erzeugt eine Object-Datei. Mehrere Object-Dateien und Bibliotheken können anschließend mit einem Linker zu einem ausführbaren Programm verbunden werden.
Zu den verbreiteten C-Compilern gehören GCC, der freie Compiler der GNU Compiler Collection, und unter Windows Visual C++. Da C wenige Schlüsselwörter hat, können Compiler vergleichsweise einfach und klein sein. Auf neuen Computersystemen ist C deshalb oft eine der ersten verfügbaren Programmiersprachen nach Maschinencode und Assembler.
Undefiniertes Verhalten und Sicherheit
Undefiniertes Verhalten, auf Englisch undefined behavior, ist nach dem C-Standard „Verhalten bei Verwendung eines nicht portablen oder fehlerhaften Programmkonstrukts oder von fehlerhaften Daten, an die diese internationale Norm keine Anforderungen stellt“. Beispiele sind die Dereferenzierung eines Nullzeigers, Division durch Null, Zugriff auf Variablen durch Zeiger eines falschen Typs oder Überlauf bei vorzeichenbehafteten Ganzzahlen.
Compiler dürfen annehmen, dass korrektes Programmieren kein undefiniertes Verhalten enthält. Deshalb können Optimierungen Code entfernen oder verändern, der unter dieser Annahme als unnötig gilt. Das kann dazu führen, dass Programme mit anderen Optimierungsstufen oder neueren Compilerversionen unerwartet fehlerhaft laufen. Dieses Verhalten wird teilweise kontrovers diskutiert und kann zu Sicherheitslücken führen.
C ist auf einfache Kompilierbarkeit und schnellen Programmablauf ausgelegt. Compiler erzeugen aber meist nur wenig zusätzlichen Code zur Laufzeitprüfung. Direkte Speicherzugriffe werden kaum eingeschränkt, wodurch der Compiler bei der Fehlersuche nur begrenzt helfen kann. Deshalb ist C für sicherheitskritische Anwendungen wie Medizintechnik, Verkehrsleittechnik oder Raumfahrt weniger geeignet. Wird C dort dennoch eingesetzt, versucht man die Qualität unter anderem durch zusätzliche Prüfungen und Softwaretests mit hoher Testabdeckung zu erhöhen.
Ein Beispiel für sicherheitskritische Bibliotheksfunktionen ist gets() aus alten Standards. Bei zu langer Eingabe kann sie fremde Speicherbereiche überschreiben, also einen Pufferüberlauf verursachen. Aktuelle Implementierungen unterstützen solche Funktionen teils aus Gründen der Kompatibilität mit altem Quellcode weiter, warnen aber oft bei der Übersetzung. gets() wurde mit C11 endgültig aus der Sprachspezifikation entfernt. Außerdem ist C nicht typsicher, weil verschiedene Datentypen zuweisungskompatibel behandelt werden können.
Lernvideos zu C (Programmiersprache)
6:47
Satz des Pythagoras | a² + b² = c² | Mathematik - einfach erklärt | Lehrerschmidt
Lehrerschmidt · 1,5 Mio. Aufrufe
9:18
What is a mutex in C? (pthread_mutex)
CodeVault · 212.970 Aufrufe
2:13
E = m * c² - Einsteins Relativitätstheorie #TheSimpleShort
Physik - simpleclub · 120.974 Aufrufe
12:19
Fugenanalyse, Wie analysiert man eine Fuge? Bach C-Dur Fuge, Wohltemperiertes Klavier
Digitale Schule · 88.582 Aufrufe