C Grundlagen
Ursprünge von C
Die Programmiersprache C gehört zu den bedeutendsten Sprachen der
Informatikgeschichte. Sie entstand
Anfang der 1970er Jahre in den Bell Laboratories in den USA.
Dennis Ritchie, Informatiker bei den Bell Labs, gilt als „Vater von C“. Gemeinsam mit Ken
Thompson
arbeitete er an dem Betriebssystem Unix.
Ursprünglich wurde Unix in Assembler entwickelt. Assembler hat den Vorteil, dass es sehr direkten
Zugriff auf die Hardware ermöglicht und äußerst effizient ist. Gleichzeitig bringt diese Nähe zur
Maschine aber große Nachteile mit sich: Der Code ist schwer lesbar, aufwendig zu warten und nahezu
vollständig an die jeweilige Prozessorarchitektur gebunden. Ein Programm, das für einen bestimmten
Rechner geschrieben wurde, lässt sich deshalb nicht ohne Weiteres auf einer anderen Hardware ausführen –
man müsste den gesamten Assemblercode anpassen.
Genau dieses Problem löste die Einführung von C. Mit C konnte Unix fast vollständig neu geschrieben
werden. Der neue Quellcode war nicht nur wesentlich leichter verständlich und strukturierter, sondern
vor allem auch portierbar. Das bedeutete, dass Unix nun relativ einfach auf unterschiedliche
Rechnerarchitekturen übertragen werden konnte.
Diese Eigenschaft machte C zu einem entscheidenden Meilenstein in der Softwareentwicklung und trug
maßgeblich dazu bei, dass sich Unix – und damit auch C – weltweit verbreiten konnte.
Bedeutung von C
C ist die „Mutter“ vieler späterer Sprachen:
-
C++(objektorientierte Erweiterung von C) -
Java(sieht in Syntax und Konzepten stark nach C aus) -
C#,Objective-C,Go
und viele andere.
Bis heute nutzen fast alle modernen Programmiersprachen Ideen und Syntax-Elemente von C.
Dennis Ritchie und Ken Thompson bekamen dafür 1983 den Turing Award (die höchste Auszeichnung der
Informatik).
Einsatzgebiete von C
Die Sprache C wurde nicht nur als akademisches Projekt entwickelt, sondern hat seit den 1970er Jahren unzählige Anwendungen gefunden. Der große Vorteil von C liegt darin, dass es direkten Zugriff auf die Hardware erlaubt und gleichzeitig in einer hochsprachlichen Syntax geschrieben wird, die für Menschen lesbarer ist als Assembler. Schwerpunkte für den Einsatz von C sind sowohl für die Entwicklung von Systemsoftware als auch die Programmierung von Mikrocontrollern und eingebetteten Systemen (Embedded Systems).
C, die Brücke zu Mikrocontrollern
Mikrocontroller sind im Grunde vollständige Computer, die in einem einzigen
Chip integriert sind. Im
Unterschied zu den leistungsstarken Prozessoren in PCs oder Smartphones verfügen sie meist nur über sehr
begrenzte Ressourcen: wenige Kilobyte bis wenige Megabyte Speicher, geringe Taktfrequenzen und stark
eingeschränkte Rechenleistung.
Mikrocontroller bilden sie das Herz zahlloser elektronischer Geräte des Alltags. Sie übernehmen
Steuerungsaufgaben in Autos, werten Sensordaten in Haushaltsgeräten aus, treiben kleine Displays an oder
kontrollieren ganze Produktionsmaschinen. Auch in Robotern und modernen Smart-Home-Geräten sorgen sie
dafür, dass Sensoren und Aktoren zuverlässig zusammenarbeiten.
Weil Mikrocontroller mit wenig Ressourcen auskommen müssen, ist eine effiziente Programmierung
entscheidend.
Hier zeigt C seine Stärken: Der direkte Zugriff auf Speicher und Hardware ermöglicht es, den vorhandenen
Platz optimal zu nutzen und Programme so klein und schnell wie möglich zu halten.
Das Arduino Framework nutzt intern C/C++.
Vorteil für Einsteiger: Arduino versteckt die komplizierten Teile (Compiler, Toolchain), man schreibt
„fast wie in C“ und bekommt direkten Zugriff auf die Hardware.
Die Grundstruktur eines C Programms
Ein C-Programm folgt immer einer klaren Grundstruktur. Diese besteht aus drei wichtigen Teilen:
- Die Präprozessor-Direktiven (Compiler-Direktiven)
- Eigene Funktionen
-
Die
main()Funktion
Präprozessor und Präprozessor-Direktiven in C
Der Präprozessor – was ist das?
Bevor der eigentliche Compiler den C-Code übersetzt, läuft ein eigenes kleines Programm: der
C-Präprozessor.
Der Päprozessor bereitet den Quellcode auf, fügt externe Bausteine (Bibliotheken) hinzu, entfernt
Kommentare (die für den Compiler unwichtig sind), ersetzt Symbole oder Konstanten durch Werte.
Erst danach wird der vorbereitete Code an den Compiler übergeben, der daraus in einem mehrstufigen
Prozess der Maschinencode erzeugt.
Was sind Präprozessor-Direktiven?
Präprozessor-Direktiven sind Anweisungen für den Präprozessor, die mit # beginnen.
Sie steuern wie der Quellcode vorbereitet wird. Sie gelten also als Compiler-Direktiven (weil sie den Ablauf der Übersetzung beeinflussen).
Wichtige Präprozessor-Direktiven
#include – Bibliotheken (Libraries) einbinden
Damit bindet man fertigen Code ein, der in einer separaten Datei (Bibliothek /
Library) gespeichert ist.
Beispiel:
#include <stdio.h> // Standard Input/Output Bibliothek
#define – Konstanten und Makros
Mit #define legt man symbolische Namen fest.
Beispiel:
#define PI 3.14159
Im Quellcode wird jedes PI vor dem Compilieren mit dem Wert 3,14159 ersetzt.
#ifdef / #endif – bedingte Übersetzung
Man kann mit dieser Direktive bestimmte Codebereiche nur dann übersetzen lassen, wenn eine Bedingung erfüllt ist.
Beispiel:
#define DEBUG #ifdef DEBUG printf("Debug-Modus aktiv!\n"); #endif
Ausgabe mit printf() erscheint nur, wenn DEBUG definiert ist.
Eigene Funktionen (optional)
In C kann man man zusätzliche Funktionen definieren. Funktionen sind
Programmbausteine, die eine
bestimmte Aufgabe erfüllten. Vorteil: Wiederverwendbarkeit und bessere Übersichtlichkeit.
Funktionen müssen in C immer definiert werden bevor sie im Quellcode das erste Mal verwendet werden.
Beispiel:
void begruessung() { printf("Hallo, willkommen im Programm!\n"); }
Die Funktion begruessung() kann nun im Quellcode
verwendet werden.
Hauptfunktion main()
Die main() Funktion ist Pflicht in jedem C-Programm. Sie
ist der Startpunkt des Programms. Das Betriebssystem sucht beim Start eines C Programms immer zuerst
nach main().
Beispiel:
int main() { // Hier beginnt das eigentliche Programm printf("Programm startet!\n"); return 0; // Rückgabe ans Betriebssystem }
Ablauf beim Programmstart
Wenn man ein C-Programm startet, passiert im Hintergrund:
- Das Betriebssystem lädt das Programm in den Speicher.
-
Es sucht nach der Funktion
main(). - Ab hier laufen alle Anweisungen in der festgelegten Reihenfolge.
-
Wenn
main()endet (durchreturnoder durch das Erreichen des Blockendes), wird das Programm beendet.
Beispiel für ein einfaches C Programm:
#include <stdio.h> // Bibliothek einbinden // Eigene Funktion void begruessung() { printf("Hallo, willkommen im Programm!\n"); } // Hauptprogramm int main() { begruessung(); // Funktionsaufruf printf("Programm läuft...\n"); return 0; // Ende des Programms }
Ablauf des Programms:
-
Der Präprozessor fügt die Bibliothek
stdio.hein. -
Die Funktion
begruessung()wird definiert. -
Das Programm startet in
main(). -
main()ruftbegruessung()auf → Textausgabe. - Weitere Ausgabe.
-
Ende mit
return 0;.
Einfache Bildschirmausgabe mit C
Zu Beginn des Programmierens steht traditionell das berühmte „Hallo Welt!“-Programm.
Denn das Wichtigste ist zunächst, dass der Computer die Ergebnisse eines Programms auch sichtbar
macht. Am einfachsten geschieht dies durch die Ausgabe von Text auf dem Bildschirm.
In C erfolgt die einfache Textausgabe über den Befehl printf(). Mit ihm können Zeichenketten, Zahlen
oder kombinierte Ausdrücke auf dem Bildschirm dargestellt werden. Damit diese Funktion jedoch
überhaupt zur Verfügung steht, muss zu Beginn des Programms die Standardbibliothek
für Ein- und Ausgabe eingebunden werden.
Beispiel für "Hallo Welt!" in C:
#include <stdio.h> // Bibliothek einbinden int main() { printf("Hallo Welt!"); return 0; // Ende des Programms }
#include <stdio.h>
-
bindet die Bibliothek ein, die
printf()bereitstellt. -
stdio.hsteht für Standard Input/Output Header und stellt wichtige Funktionen bereit – darunterprintf()für Ausgaben undscanf()für Eingaben. Ohne diese Einbindung erkennt der Compiler den Funktionsnamenprintf()nicht und meldet einen Fehler.
printf("...");
- Gibt den Text auf dem Bildschirm aus.
return 0;
- kehrt zum Betriebssystem zurück.
- 0 (Fehlercode) steht für die fehlerfreie Ausführung des Programms
Dabei ist zu beachten, dass jeder Befehl in C mit einem Semikolon ; abgeschlossen werden muss! Andernfalls liefert der
Compiler einen Fehler.
Grundlegende Syntax von C-Quellcode
Syntax von Befehlen in C
In C endet jede Anweisung mit einem Semikolon (;).
Fehlt dieses Abschlusszeichen, kann der Compiler den
Befehl nicht korrekt verarbeiten und meldet einen Fehler.
Außerdem ist C case-sensitiv – das bedeutet, dass zwischen Groß- und Kleinschreibung
unterschieden wird.
So sind etwa main, Main und MAIN drei völlig verschiedene Bezeichner. Dies ist vor allem bei der
Benennung von Variablen und Funktionen zu beachten.
Code-Blöcke in C
In C lassen sich mehrere Anweisungen zu Blöcken zusammenfassen, wodurch
Programme übersichtlich und hierarchisch strukturiert werden.
Ein Block beginnt stets mit einer öffnenden geschweiften Klammer { und
endet mit einer schließenden
geschweiften Klammer }.
Kommentare
Kommentare dienen dazu, den Quellcode für Menschen leichter verständlich zu machen. Sie haben keinen Einfluss auf die Ausführung des Programms, sondern sind ausschließlich für den Leser gedacht.
Besonders in größeren Projekten, an denen mehrere Personen zusammenarbeiten, ist eine klare und durchdachte Kommentierung unverzichtbar. Sie erleichtert nicht nur die Zusammenarbeit im Team, sondern auch die spätere Wartung und Weiterentwicklung des Codes – sei es durch andere Entwickler oder durch einen selbst, wenn man den eigenen Code nach längerer Zeit erneut betrachtet.
Die Sprache C kennt zwei verschiedene Arten von Kommentaren: einzeilige und mehrzeilige.
- Einzeilige Kommentare beginnen mit // und reichen bis zum Ende der aktuellen Zeile.
- Mehrzeilige Kommentare werden mit /* eingeleitet und mit */ abgeschlossen. Sie können sich über mehrere Zeilen erstrecken.
Beispiel: Kommentare in C
// Einzeiliger Kommentar /* Mehrzeiliger Kommentar */
Besonders praktisch ist die Möglichkeit, mit einem mehrzeiligen Kommentar ganze Abschnitte des
Quellcodes „auszukommentieren“. Dabei wird dieser Code vom Compiler
vollständig ignoriert, ohne dass man ihn löschen muss.
Diese Technik ist im Alltag äußerst nützlich, etwa wenn man beim Testen von Programmen bestimmte
Funktionen zeitweise deaktivieren möchte oder verschiedene Varianten von Code ausprobiert.
Variablen in C
Damit ein Programm Informationen verarbeiten kann, müssen Daten im Arbeitsspeicher des Computers abgelegt werden. Dieser Speicher besteht aus
einer großen Menge einzelner Speicherzellen, die jeweils durch eine eindeutige Adresse gekennzeichnet sind.
Für den Programmierer wäre es jedoch unpraktisch und fehleranfällig, Daten direkt über solche
numerischen Adressen zu verwalten.
Hier kommen Variablen ins Spiel. Eine Variable ist ein benannter
Speicherbereich im Arbeitsspeicher (an einer bestimmten Adresse), in dem ein
Wert abgelegt und später wieder verändert werden kann.
Der Variablen-Bezeichner (Variablenname) dient als verständlicher
Verweis auf diesen Speicherbereich, sodass der Programmierer nicht mit reinen Speicheradressen arbeiten
muss.
In der Programmiersprache C nimmt die Organisation und effiziente Nutzung des Arbeitsspeichers
eine zentrale Rolle ein.
Anders als in vielen modernen Sprachen, die Speicherverwaltung teilweise oder vollständig
automatisieren, gibt C dem Entwickler die direkte Kontrolle über:
- die Größe des reservierten Speicherbereichs
- den Datentyp der abgelegten Information (z. B. Ganzzahl, Kommazahl, Zeichen)
- die präzise Organisation des verfügbaren Arbeitsspeichers
Diese Nähe zur Hardware ist einer der Gründe, warum C bis heute besonders für Systemprogrammierung und Mikrocontroller-Anwendungen genutzt wird, wo die effiziente Verwaltung begrenzter Ressourcen entscheidend ist.
Datentypen in C
Ein Datentyp legt fest, welche Art von Daten in einer Variablen gespeichert werden können und wie groß der dafür benötigte Speicherbereich mindestens sein muss. Außerdem bestimmt er, wie der Inhalt im Arbeitsspeicher dargestellt wird (z. B. als Ganzzahl oder Kommazahl).
C kennt folgende Datentypen:
|
Datentyp |
Mindestgröße laut Standard |
Typische Größe (PC, 32/64 Bit) |
Wertebereich (Beispiel, 32-Bit-Compiler) |
|---|---|---|---|
|
char |
8 Bit (1 Byte) |
8 Bit |
-128 … 127 oder 0 … 255 |
|
int |
≥ 16 Bit |
meist 32 Bit |
-2.147.483.648 … 2.147.483.647 |
|
long |
≥ 32 Bit |
32 oder 64 Bit |
abhängig von System und Compiler |
|
long long |
≥ 64 Bit |
64 Bit |
sehr große Ganzzahlen |
|
float |
ca. 32 Bit (mind. 6 Stellen Genauigkeit) |
32 Bit |
ca. 7 Nachkommastellen |
|
double |
ca. 64 Bit (mind. 10 Stellen Genauigkeit) |
64 Bit |
ca. 15 Nachkommastellen |
|
long double |
≥ wie |
Plattformabhängig |
noch höhere Genauigkeit |
Bei der Wahl des passenden Datentyps spielen drei Gesichtspunkte eine Rolle:
Speichergröße
Variablen belegen Platz im Arbeitsspeicher.
-
Kleine Datentypen (
char,int) sparen Speicher – wichtig auf Mikrocontrollern. - Der Typ muss aber groß genug sein, um den benötigten Wertebereich abzudecken.
Genauigkeit
-
Ganze Zahlen (
int,long) sind exakt, aber ohne Nachkommastellen. -
Kommazahlen (
float,double) erlauben Nachkommastellen, haben aber Rundungsfehler.
Performance
- Prozessoren arbeiten am schnellsten mit ihrer nativen Wortbreite (int auf PCs meist 32 Bit).
- Auf kleinen Mikrocontrollern können 8- oder 16-Bit-Typen schneller und sparsamer sein.
-
Gleitkommazahlen sind oft langsamer, besonders wenn die CPU keine Hardware
Floatingpoint Unit(FPU) besitzt.
Zeichenketten in C
Wie man anhand der Datentypen sieht, liegt der Schwerpunkt bei C eindeutig auf Zahlen – ganze Zahlen,
Kommazahlen, Vorzeichen und Genauigkeit spielen eine zentrale Rolle.
Doch Programme arbeiten nicht nur mit Zahlen, sondern müssen auch mit Texten umgehen können: Namen,
Meldungen oder ganze Wörter.
In C gibt es dafür den Datentyp char für einzelne Zeichen. Mehrere
char-Elemente hintereinander ergeben eine Zeichenkette
(englisch: String).
Im Gegensatz zu vielen modernen Programmiersprachen wie Python oder Java gibt es in C keinen eigenen
Datentyp string.
-
C kennt nur den Datentyp
charfür ein einzelnes Zeichen. -
Eine Zeichenkette wird in C als
Arrayvonchardargestellt, also eine Folge von Zeichen, die hintereinander im Arbeitsspeicher abgelegt sind. - Das Ende einer Zeichenkette wird durch das besondere Nullzeichen '\0' markiert. Dieses unsichtbare Zeichen signalisiert dem Programm, wo die Zeichenkette endet. Man bezeichnet dies auch als Nullterminierung.
Deklaration und Initialisierung von Variablen
Deklaration von Variablen
Unter Deklaration versteht man die Bekanntmachung einer Variablen beim
Compiler.
Dabei wird festgelegt:
- Datentyp → bestimmt, welche Art von Werten gespeichert werden kann (z. B.
int,float,char). - Name → eindeutiger Bezeichner für die Variable.
Bei der Deklaration wird Speicherplatz reserviert, aber der Speicher-Inhalt ist noch undefiniert (beliebiger „Müllwert“ im RAM).
Regeln für Variablennamen in C
Für Variablen-Bezeichner sind nur bestimmte Zeichen erlaubt:
-
Buchstaben (
a–z,A–Z) -
Ziffern (
0–9) -
Unterstrich (
_) - Bezeichner in C sind case-sensitiv.
Wichtig!
- Ein Variablen-Bezeichner darf nicht mit einer Zahl beginnen
- Sonderzeichen, Leerzeichen, Umlaute u.a. sind nicht erlaubt!
Reservierte Schlüsselwörter
Wörter wie int, for, return sind
fest für die Sprache C reserviert und dürfen nicht als Variablenname benutzt werden.
Initialisierung von Variablen
Unter Initialisierung versteht man das erste Zuweisen eines Werts für die
Variable.
Die Initialisierung kann direkt bei der Deklaration geschehen oder später im Programmcode.
Wichtig! Variablen müssen zuerst deklariert werden bevor sie initialisiert werden.
Beispiel für die Deklaration und Initialisierung von Variablen in C:
#include <stdio.h> int main() { int a; // nur Deklaration, a enthält zufälligen Wert int b = 5; // Deklaration + Initialisierung a = 3; // nachträgliche Zuweisung (Initialisierung) printf("a = %d, b = %d\n", a, b); return 0; }
Deklaration einer Zeichenkette in C
Eine Zeichenkette wird als Array von char deklariert.
Es gibt mehrere Möglichkeiten ein char-Array zu deklarieren und zu
initialisieren.
Achtung! Die Initialisierung eines Arrays mit einer vorgegebenen Zeichenkette ist nur bei der Deklaration erlaubt!
Deklaration ohne Initialisierung
Bei der Deklaration ohne Initialisierung muss immer die Länge des Arrays angegeben werden.
Beispiel für die Deklaration einer Zeichenkette in C:
char Zeichenkette[21] // Platz für bis zu 19 Zeichen + 1 Nullzeichen
Wichtige Punkte bei der Wahl der Array-Länge für Zeichenketten
- Nullterminierung beachten: Am Ende jeder Zeichenkette steht automatisch das Zeichen '\0'. Eine Zeichenkette mit 20 Zeichen benötigt daher ein Array mit 21 Elementen.
- Feste Länge: Die Größe eines Arrays ist nach der Deklaration unveränderlich.
- Länge nicht unterschätzen: Schon bei etwas längeren Texten, z. B. für Ausgaben oder Meldungen, können leicht über 100 Zeichen zusammenkommen.
- Risiko bei Überlauf: Wird mehr Text in ein Array geschrieben, als Platz vorhanden ist, kommt es zu undefiniertem Verhalten – von falschen Ausgaben bis hin zu Programmabstürzen.
- Besonderheit bei Mikrocontrollern: Dort steht oft nur sehr wenig Arbeitsspeicher zur Verfügung. Arrays sollten also so groß wie nötig, aber so klein wie möglich gewählt werden.
Direkte Initialisierung mit einer Zeichenkette
Beispiel für die direkte Initialisierung bei der Deklaration einer Zeichenkette in C:
char text[] = "Hallo";
Der Compiler erzeugt automatisch das Array:
{'H','a','l','l','o','\0'}
Die Größe wird automatisch bestimmt (hier: 6 Zeichen inkl. \0).
Direkte Initialisierung mit einer Zeichenkette und fester Größe
Beispiel für die Initialisierung bei der Deklaration einer Zeichenkette in C:
char text[21] = "Hallo";
Das Array hat 21 Plätze, nur die ersten 6 werden belegt ("Hallo\0").
Die restlichen Plätze werden mit \0 aufgefüllt.
Formatierte Bildschirmausgabe in C
Die printf() Funktion, ermöglicht eine formatierte
Bildschirmausgabe im Terminal.
Die printf() Funktion ist in der <stdio.h> Bibliothek enthalten. Diese muss vor der Verwendung
eingebunden werden.
Syntax:
printf("Ausgabetext", Variable, Variable, … );
"Ausgabetext": Text mit Formatanweisungen für
die auszugebende Variable
|
Variable: Bezeichner der Variablen, deren Inhalt
ausgegeben werden soll.
|
Formatanweisungen
%d
|
Ganzzahl (Integer), dezimal |
%i |
Ganzzahl, dezimal |
%o |
Ganzzahl, oktal |
%h |
Ganzzahl, hexadezimal |
%u |
Ganzzahl, vorzeichenlos (unsigned integer) |
%c |
Character |
%s |
String (nullterminertes Char-Array) |
%f |
Fließkommazahl (Float) |
%f.2 |
Fließkommazahl (Float), angezeigt mit 2 Nachkommastellen |
%p |
Zeiger (Pointer), hexadezimal |
Beispiel für die formatierte Ausgabe im Terminal:
#include <stdio.h> int a = 42; int main() { // Zeichenkette für die Formatierte Ausgabe // printf("Der Wert von a betraegt: %d",a); }
Sonderzeichen in Zeichenketten
In C lassen sich in Zeichenketten Steuer- und Sonderzeichen verwenden.
-
\n= Zeilenumbruch -
\t= Tabulator (Einrückung) -
\"= Anführungszeichen -
\\= Backslash
Mathematische Berechnungen
C unterstützt alle Grundrechenarten:
-
Addition:
+ -
Subtraktion:
- -
Multiplikation:
* -
Division:
/ -
Modulo (Rest einer Division):
%(nur für Ganzzahlen)
Berechnungen mit Ganzzahlen (int)
Mit dem Datentyp int (Ganzzahlen) werden nur
ganze Zahlen gespeichert.
Bei der Division von zwei Ganzzahlen wird das Ergebnis abgeschnitten. Die Nachkommastellen gehen
verloren.
Division zweier Ganzzahlen:
#include <stdio.h> int a, b, Ergebnis; int main() { a = 12; b = 5; Ergebnis = a / b; printf("%d / %d = %d\n",a, b, Ergebnis); }
Bildschirmausgabe:
2
Berechnungen mit Fließkommazahlen (float, double)
Mit float oder double (Fließkommazahlen) werden Nachkommastellen gespeichert.
Die Division liefert ein numerisch exaktes Ergebnis (so weit es der Datentyp
erlaubt).
Division zweier Ganzzahlen:
#include <stdio.h> float a, b, Ergebnis; int main() { a = 12; b = 5; Ergebnis = a / b; printf("%f / %f = %f\n",a, b, Ergebnis); }
Bildschirmausgabe:
2.4
Unterschied Integer vs. Float
-
Integer-Division: Ergebnis wird abgeschnitten (
7 / 2 = 3). -
Float-Division: Ergebnis wird mit Nachkommastellen dargestellt (
7.0 / 2.0 = 3.5). -
Mischung von Typen: Wenn
intundfloatkombiniert werden, wandelt C denintin einenfloatum (implizite Typkonvertierung).
Funktionen in C
Was sind Funktionen?
Eine Funktion ist ein eigenständiger Programmblock, der eine bestimmte Aufgabe erledigt.
- Funktionen helfen, Programme übersichtlicher und wiederverwendbarer zu machen.
- Jede Funktion hat einen Namen.
- Eine Funktion kann Eingaben (Parameter) erhalten.
- Eine Funktion kann eine Ausgabe (Rückgabewert) liefern.
Aufbau einer Funktion
Eine Funktion ist in C wie folgt aufgebaut:
Datentyp Funktionsname(Parameterliste) {
// Anweisungen
// Anweisungen
return Wert;
}
- Alle Funktionen in C, auch wenn sie keinen Wert zurückgeben, müssen für einen bestimmten Datentyp definiert werden.
- Prinzipiell können mehrere Parameter unterschiedlichen Datentyps an eine Funktion übergeben werden. Wird kein Wert vom Hauptprogramm an die Funktion übergeben, ist die Parameterliste leer.
- Funktionen in C können höchstens einen Rückgabewert besitzen!
Funktionen ohne Rückgabewert
Für Funktionen, die keine Werte zurückgeben existiert in C der Datentyp void.
Beispiel für eine Funktion ohne Rückgabewert:
#include <stdio.h> void begruessung() { printf("Hallo, willkommen im Programm!\n"); } int main() { begruessung(); // Funktionsaufruf printf("Programm läuft...\n"); return 0; }
Übergabeparameter
Übergabe-Parameter sind Werte, die vom Hauptprogramm an die Funktion übergeben werden. Sie liefern die notwendigen Eingangsdaten, damit die Funktion ihre Aufgabe erfüllen kann – zum Beispiel, um interne Berechnungen durchzuführen oder Ergebnisse individuell anzupassen.
Allgemeine Syntax einer Parameterliste
-
Jeder Parameter hat einen
Datentypund einen Namen. -
Parameter werden in runden Klammern
(...)aufgelistet. -
Mehrere Parameter werden durch Kommas
,getrennt.
Beispiel für eine Funktion mit einem Parameter:
int quadrat(int x) { return x * x; }
-
int: Datentyp des Parameters -
x: Name des Parameters
Beispiel für eine Funktion mit mehreren Parametern:
int summe(int a, int b) { return a + b; } int main() { int x = 7, y = 3; printf("Summe: %d\n", summe(x, y)); return 0; }
-
Parameterliste: (
inta,intb) - Jeder Parameter hat seinen eigenen Datentyp und Namen.
- Es können auch unterschiedliche Datentypen übergeben werden.
- Die Reihenfolge der Parameter ist verbindlich beim Funktionsaufruf.
- Beim Aufruf werden die Werte in der gleichen Reihenfolge übergeben, wie sie in der Parameterliste definiert sind.
Gültigkeitsbereich von Variablen (Scope)
Der Gültigkeitsbereich (engl. Scope) einer
Variablen bestimmt, wo im Programm diese Variable sichtbar und nutzbar ist.
In C unterscheidet man im Wesentlichen globale und lokale Variablen.
Globale Variablen
Globale Variablen werden außerhalb von Funktionen (meist am Anfang des Programms) deklariert.
- Sind im gesamten Programm sichtbar – also in allen Funktionen.
- Belegen Speicherplatz während der gesamten Programmlaufzeit.
- Vorteil: Einfacher Zugriff aus verschiedenen Funktionen.
- Nachteil: Gefahr unbeabsichtigter Änderungen, schlecht nachvollziehbarer Code.
Beispiel für globale Variablen:
#include <stdio.h> int counter = 0; // globale Variable void zaehler() { counter++; // Zugriff von überall möglich } int main() { zaehler(); printf("Counter = %d\n", counter); zaehler(); printf("Counter = %d\n", counter); return 0; }
Bildschirmausgabe:
counter = 1
counter = 2
Lokale Variablen
Lokale Variablen werden innerhalb einer Funktion oder eines Blocks ({ ... }) deklariert.
-
Sichtbarkeit (
Scope): Nur innerhalb der Funktion oder des Blocks. - Andere Teile des Programms, die außerhalb des Blocks sind, haben keinen Zugriff auf lokale Variablen.
- Dadurch können lokale Variablen nicht versehentlich überschrieben werden.
- Unterschiedliche Funktionen können lokale Variablen mit demselben Namen haben, ohne dass Konflikte entstehen.
- Lebensdauer: Nur während der Ausführung der Funktion.
- Wird die Funktion erneut aufgerufen, wird die Variable neu erzeugt und wieder mit ihrem Startwert initialisiert.
Wichtig!
Wenn eine lokale Variable denselben Namen wie eine globale hat, verdeckt die lokale Variable die
globale Variable im jeweiligen Block.
Beispiel für lokale Variablen:
#include <stdio.h> void zaehler() { int x = 0; // lokale Variable x++; printf("x = %d\n", x); } int main() { zaehler(); // Ausgabe: x = 1 zaehler(); // Ausgabe: x = 1 (neu erzeugt!) return 0; }
Bildschirmausgabe:
x = 1
x = 1
Beispiel für lokale und globale Variablen:
#include <stdio.h> int counter = 5; // globale Variable void zaehler() { int counter = 0; // lokale Variable counter++; printf("counter = %d\n", counter); } int main() { zaehler(); // Ausgabe: x = 1 printf("counter = %d\n", counter); // Ausgabe: counter = 5 return 0; }
Bildschirmausgabe:
counter = 1
counter = 5