Die Sprachen C und C++
C und C++ sind Programmiersprachen, also Sprachen, mit denen Computerprogramme geschrieben werden.
Programmieren beschreibt das Handwerk, einem Computer beizubringen, dass er eine gewünschte Tätigkeit, einen klar definierten Prozess ausführen soll. Wie in jedem Prozess gibt es beim Programmieren Rohmaterial, das mit geeigneten Werkzeugen zu einem gewünschten Ergebnis verarbeitet wird. Das Rohmaterial ist durch die Begriffe Daten
, Werte
und Informationen
zu beschreiben. Das Werkzeug ist die Programmiersprache.
Programmierung kann als die Steuerung eines Daten-Fluss verstanden werden. In mehreren hintereinandergehängten Modulen werden jeweils Daten eingelesen, verarbeitet und danach ausgegeben, wobei die ausgegebenen Daten von darauffolgenden Modulen wieder eingelesen werden, und so weiter und so fort.
Dieser Fluss ist die grundlegende Motivation der Programmierung und kann wie bei allen Programmiersprachen auch in sämtlichen Entwicklungsphasen der Sprachen C und C++ beobachtet werden.
Vom elektrischen Strom zu Bits und Bytes
Elektrischer Strom wurde lange Zeit als reinen Energielieferanten betrachtet: Er wird durch Generatoren erzeugt, durch Leitungen transportiert und in Widerständen wie Glühbirnen verbraucht. Dieses Konstrukt wird zusammengefasst unter dem Namen Elektrik
. Im Gegensatz dazu behandelt die ElektrONik
die Nutzung einer messbaren Grösse des Stroms, beispielsweise die Stromstärke.
Es ist noch nicht lange her, seit die ersten elektronischen Schaltungen erfunden wurden: Eine Methode, mit der elektrischer Strom kontrolliert auf verschiedene Leitungen verteilt werden kann. Das Zusammenfügen mehrerer Schaltungen und Leitungen führte zu den ersten elektronischen Geräten: Einfache Steuerelemente wie beispielsweise automatische Türöffner, Zeitschaltuhren oder die Blinklichter eines Autos. Diese Steuerelemente wandeln stets irgendwelche Eingangssignale wie beispielsweise einen Tastendruck durch eine mehr oder weniger komplizierte Verknüpfung verschiedener Schaltungen in Ausgangssignale um. Erfüllt eine Zusammenstellung von Schaltungen einen bestimmten Zweck, so wird sie als sogenannt integrierte Schaltung
in einen Chip
gepackt, welcher als Ganzes die gewünschte Funktion ausführt.
Elektronische Bauteile wie Chips werden aufgrund ihrer physikalischen Greifbarkeit Hardware
genannt. Mit der Zeit wurden die Ansprüche an Hardware immer höher und die Verknüpfungen in den Chips wurden immer komplizierter. Um beliebig komplexe Funktionen ausführen zu können, wurde schliesslich der programmierbare Chip erfunden, ein Chip, der nicht nur eine bestimmte Funktion ausführen kann, sondern ein ganzes Set von grundlegenden Befehlen, darunter beispielsweise auch Addieren und Subtrahieren. Zusammen mit einem elektronischen Modul, welches Informationen zwischenspeichern kann (und auch heute noch als der Speicher
bekannt ist), können beliebig komplexe Funktionsabläufe mittels eines einzigen Chips erledigt werden. Dies wird noch heute als die CPU, Central Processing Unit bezeichnet, oder schlicht: Den Prozessor.
In einem Prozessor eines modernen Computers werden anhand der Stromstärke zwei Zustände spezifiziert, bei denen entweder mehr oder weniger Strom als eine bestimmte Schwelle fliesst. Diese beiden Zustände Strom
und Nicht-Strom
definieren die Basiseinheit Bit
eines modernen Computers, wobei die Zustände besser bekannt sind als 1 und 0. Durch eine Aufreihung mehrerer Bits entstehen kombinierte Zustände: Acht Bits zusammen ergeben ein Byte, womit 256 verschiedene Zustände möglich sind, mehr Bits ergeben dementsprechend mehr Zustände. Alles, was mittels eines Zustands dargestellt werden kann, wird als Daten
(im Singular: ein Datum
) bezeichnet.
Maschinensprache und Assembler
Ein Prozessor weiss nicht von sich aus, wie Daten zu handhaben sind. Ob das Datum 11001000 nun die positive Zahl 200 representiert oder die negative Zahl -56, hat für einen Prozessor keine Relevanz, er arbeitet stets mit reinen Daten. Zu früheren Zeiten hatte ein Programmierer somit die Aufgabe, den Prozessor anzuweisen, welche Manipulationen er ausführen soll, damit die Daten korrekt verarbeitet werden (EDV = elektronische Datenverarbeitung).
Damit ein Prozessor weiss, was genau er verarbeiten soll, braucht er Instruktionen, einen Code, welcher genau vorgibt, wann welche Eingangsdaten mit welcher Methode verknüpft werden sollen. Die Zusammenstellung eines Codes wird Software
genannt und hat die Aufgabe, die Hardware zu steuern, zu kontrollieren. Eine Abfolge von Instruktionen für einen Prozessor wird Maschinen-Programm
genannt, welches in der einzigen für den Prozessor verständlichen Sprache verfasst ist: Der Maschinen-Sprache. Jeder Prozessortyp hat eine eigene Maschinensprache, die nur er versteht. Sie ist für einen Menschen grundsätzlich unverständlich, da sie nur aus binären Werten besteht, welche bestenfalls als Zahlen interpretiert werden können.
Zu alten Zeiten mussten Programmierer somit einem Prozessor Zahlenwerte übermitteln, um eine bestimmte Funktionalität zu erreichen. Da dies für einen Menschen schwierig zu handhaben ist, wurde der sogenannte Assembler
erfunden, ein Programm, welches halbwegs menschliche Wörter in die gewünschten Zahlenwerte umwandelt. Diese Wörter werden Mnemonics
genannt, was auf Deutsch Gedächtnisstütze
bedeutet. Die Sprache, die durch diese Wörter entsteht, wird genauso wie das Umwandlungsprogramm selbst auch Assembler
genannt. Folgendes ist ein Beispiel eines Assembler-Programmes:
|
Da jeder Prozessortyp seine eigene Maschinensprache hat, hat auch jeder Prozessortyp seine eigene Assemblersprache. Die Entwicklung von Prozessoren hält bis heute an, und die Organisation der Daten wurde immer wieder verändert. Dies würde bedeuten, dass ein Programmierer einen Code für jeden Prozessortyp neu schreiben müsste. Um dies zu verhindern, wurden neue Programmiersprachen entwickelt, welche sich nie verändern, im Hintergrund jedoch anhand eines Compilers
und/oder Interpreters
den Code in jeden gewünschten Assembler übersetzen. Da solche Sprachen über allen Assemblern stehen, werden sie als Hochsprachen
bezeichnet. Ein Beispiel für eine Hochsprache ist C.
Die Sprache C
Während bei Assembler der Programmierer den Prozessor explizit anweisen musste, wie er Daten zu speichern und verarbeiten hat, übernimmt bei C diese Arbeit ein Compiler
. Der Programmierer muss dem Compiler jedoch zusätzlich mitteilen, wie die Daten strukturell zu interpretieren sind. Dies ist die Definition für einen Wert
: Daten mit einer strukturellen Interpretation. In C wird die strukturelle Interpretation durch einen Typ
festgelegt.
Je nach Typ produziert ein Compiler unterschiedlichen, aber genau den zur strukturellen Interpretation passenden Maschinencode. Da in C sämtliche Werte einen Typ zugewiesen bekommen, kann der Programmierer sich somit auf die Werte konzentrieren und muss sich keine Gedanken über deren Speicherung als Daten machen. Es obliegt jedoch nach wie vor dem Programmierer, die Werte korrekt miteinander in Verbindung zu setzen, ihnen eine Bedeutung zu geben. Die Zahl 200 könnte die Anzahl Elemente in einem Array darstellen oder die Zählvariable einer Schleife. Ein Wert mit einer Bedeutung ist eine Information
. Der Umgang mit Informationen wird Informatik
genannt, oder auf Englisch Information-Technology (IT).
Sobald die Struktur von Daten bekannt ist, kann damit gearbeitet werden. Mit Werten kann ein Computer rechnen. Hier erschliesst sich die wahre Bedeutung des Wortes Computer: To compute = rechnen. Ein Computer ist gemacht, um mathematische Berechnungen auszuführen. In C wird die Verarbeitung von Werten mittels Operatoren
verwirklicht. Jeder Operator (beispielsweise eine Addition) nimmt eine bestimmte Anzahl an Eingabewerten, führt eine Verarbeitung aus und gibt einen Wert zurück. Die Ausgabe dieser Berechnung ist wiederum ein Wert, also ein Datum mit Typ. Dies bedeutet, dass jeder Operator selbst wieder als Eingabewert fungieren kann.
Durch Hintereinanderreihung oder Verschachtelung von Operatoren entstehen sogenannte Ausdrücke
. Erfüllt ein Ausdruck einen abgeschlossenen Zweck, so wird er als sogenannte Anweisung
bezeichnet. Mittels einer Anweisung gibt somit der Programmierer mehr oder weniger komplexe Befehle an den Computer. Aus diesem Grund wird die Sprache C als Befehls-Sprache (oder auch imperative Sprache
) bezeichnet.
Mehrere aufeinanderfolgende Anweisungen werden sequentiell abgearbeitet. Diese Teile des Codes sind diejenigen, an welchen der Prozessor schlussendlich Daten verarbeitet, rechnet, produktiv ist. An gewissen Stellen jedoch wird dem Prozessor mitgeteilt, dass er an eine andere Stelle im Code springen soll, beispielsweise, da er je nach Eingabewert etwas anderes ausführen soll. Eine solche Änderung des Befehlsflusses wird als Kontrollstruktur bezeichnet.
Bei sehr vielen aufeinanderfolgenden Anweisungen und Kontrollstrukturen mit komplexen, komplizierten, verwirrenden Zusammenhängen wird auch von Spaghetti-Code
gesprochen. Wenn mehrere Anweisungen und Kontrollstrukturen eine funktionale Einheit darstellen, die aus Eingabewerten eine Ausgabe erzeugen, kann dieses Konstrukt jedoch als Funktion
verpackt werden.
Sämtliche Anweisungen, Kontrollstrukturen und Funktionen werden in Textdateien geschrieben, was als Code
oder genauer Source-Code
bezeichnet wird. Die deutsche Bezeichnung Quell-Code
wird auf dieser Seite nicht verwendet.
Damit aus dem geschriebenen Code ein lauffähiges Programm entstehen kann, werden mithilfe eines Compilers
sämtliche Source-Codes zuerst in Assembler übersetzt und dann in Maschinensprache. Sehr komplexe Programme bestehen zudem aus mehreren Source-Codes und verlinken sich üblicherweise mit existierenden Bibliotheken
(auf Englisch Libraries). Um mehrere Source-Codes zusammenzufügen und um zu steuern, wie die einzelnen Teile aufeinander abzustimmen sind, besitzt C einen sogenannten Preprozessor, dem der Programmierer mit einer Vielzahl an sogenannten Direktiven
direkt im Source-Code Anweisungen geben kann. Am Ende einer Übersetzung verlinkt ein sogenannter Linker
alle übersetzten Teile und erstellt ein direkt auf dem Prozessor lauffähiges Programm.
C erlaubt es dem Programmierer zudem, ein Programm in einer übersichtlichen Form zu schreiben. Beispielsweise können alle verfügbaren Daten mit einem Namen versehen werden, was als Variable
bezeichnet wird. Der Umgang mit Werten wird erleichtert, indem mathematische Operationen mittels Symbolen wie +, -, * und / geschrieben werden können. Kontrollstrukturen können in verständlicher und gar visuell unterstützender Form dargestellt werden. Dasselbe Programm wie im obigen Assembler-Beispiel sieht in C folgendermassen aus:
|
Mit der Sprache C wurde ein Hilfsmittel geschaffen, um Datenmanipulationen schnell und geordnet durchführen zu können. Die Sprache ist durch die Nähe zu Assembler nicht immer ganz einfach, für den eingefleischten Programmierer jedoch sehr praktisch. Viele Dinge, die als Programmierer häufig geschrieben werden müssen, sind mit C vereinfacht worden. Viele bekannte kommerzielle Softwarepakete sowie die gängigen Computersysteme sind in ihrer Basis mit C programmiert worden. Die Sprache C kann auch heute noch mit anderen Sprachen konkurrenzieren, insbesondere durch die Erweiterung mit C++ auf objektorientierte Programmierung.
Die Sprache C++
C++ ist auf C aufgebaut, beinhaltet somit den kompletten Funktionsumfang von C, bietet jedoch neue Möglichkeiten in der Datenorganisation.
In C++ können zusammengehörige Werte als Informationseinheiten
deklariert werden. Zudem können dazu passende Funktionen direkt als Teil derselben Informationseinheit deklariert werden. Dieses Konstrukt aus Daten und passenden Funktionen wird als Klasse
bezeichnet und eine Informationseinheit als Objekt
oder Instanz
der Klasse. Die Werte sind als Attribute beziehungsweise Zustände der Einheit zu verstehen und werden Felder
genannt, die Funktionen sind als programmierte Eigenschaften zu verstehen, und werden Methoden
genannt.
Die Methoden einer Klasse legen fest, welche Funktionen mit den gespeicherten Daten ausgeführt werden können, aus denen die Objekte bestehen. Dies bedeutet, dass der Programmierer weder den genauen Aufbau der Daten kennen, noch denselben zu kontrollieren braucht. Es genügt, die passenden Methoden der Objekte aufzurufen. Alleine durch die Deklaration des Typs sind somit automatisch alle benötigten und passenden Methoden verfügbar. Die objektorientierte Programmierung in C++ erlaubt es zudem, Klassen ineinander zu verschachteln und Methoden über Klassen hinweg zu vererben. Zusammen mit dem Laufzeitsystem von C++ führt dies zu Polymorphismus
, einem Mechanismus, um hierarchischen Strukturen eine intuitive Semantik zuzuordnen.
Die Einkapselung von Code und Werten in Klassen strukturiert die Arbeit an der Software. Diese Modularisierung
erlaubt es, in einem Programm gesamte Bereiche je nach Bedarf einzubinden. In C++ wird dies durch sogenannte Namespaces
(Namensräume) erreicht: Methoden sind unsichtbar, solange nicht explizit der Namensraum angesprochen wird, in welchem sie deklariert wurden.
Um die Arbeit mit Objekten weiter zu vereinfachen, können in C++ nebst Methoden auch benutzerdefinierte Operatoren programmiert werden. Dies wird als Operatorenüberladung
bezeichnet und erlaubt es, für beliebig komplexe Typen beispielsweise eine Addition zu definieren. Um die Programmierarbeit zusätzlich zu erleichtern, wurden in C++ Templates
(Vorlagen) eingeführt: Eine Erweiterung der Sprache, die es erlaubt, Code ohne die Kenntnis des schlussendlich verwendeten Typs zu schreiben.
Mehr über C und C++
Hier auf dieser Seite hört die Geschichte von C und C++ auf. Als Rahmen sei hier festgehalten, dass die Sprache C aus der Sprache B entstand, welche erstmals etwa 1969 auftrat. C wurde 1972 von Dennis Ritchie, C++ wurde 1983 von Bjarne Stroustrup entwickelt. 1986 wurde mit Objective-C eine Erweiterung geschaffen. Immer wieder wurden sowohl C als auch C++ standartisiert nach ANSI und ISO. Man kennt heute insbesondere die beiden Standards C90 und C99, wobei C99 den heutzutags gültigen Standard darstellt.
Der Name C++ wurde gewählt, da es sich um eine Weiterentwicklung der Sprache C handelt. Somit wäre C+ am ehesten für den Namen geeignet gewesen. Zum einen jedoch existierte dieser Name bereits für eine andere Programmiersprache, und zum anderen ergäbe dieser Name in der Sprache selbst einen Syntax-Fehler. So war schlussendlich der Namen C++ geboren.