Eigene Funktionen
Wie in Python fasst du Anweisungen zu Funktionen zusammen — in C steht aber vor jeder Funktion ihr Rückgabetyp.
#include <stdio.h> int summe(int a, int b) { // Rückgabetyp int, zwei Parameter return a + b; } void linie(int n) { // void: kein Rückgabewert for (int i = 0; i < n; i++) { printf("-"); } printf("\n"); } int main(void) { int s = summe(3, 4); // Aufruf, Ergebnis speichern printf("Summe: %d\n", s); linie(10); return 0; }
$ gcc linien.c -o linien $ ./linien Summe: 7 ----------
- Definition:
Rückgabetyp name(Parameter) { … }— jeder Parameter bekommt einen Typ. - return:beendet die Funktion und liefert einen Wert vom Rückgabetyp zurück.
- void:Funktion ohne Rückgabewert;
return;ohne Wert ist erlaubt. - Aufruf:
summe(3, 4)— Argumente in Klammern, Ergebnis weiterverwenden oder speichern. - Kopien:Parameter erhalten Kopien der Argumente (call by value): Änderungen bleiben in der Funktion.
void verdopple(int x) { x = x * 2; // ändert nur die Kopie printf("in verdopple: %d\n", x); } int main(void) { int zahl = 5; verdopple(zahl); printf("in main: %d\n", zahl); return 0; }
in verdopple: 10 in main: 5
- Reihenfolge:C liest von oben nach unten: Eine Funktion muss vor ihrem ersten Aufruf bekannt sein.
- Prototyp:Kündigt eine Funktion an:
int summe(int a, int b);— Kopf mit Semikolon, ohne Rumpf. - Ohne Prototyp:Steht die Definition erst nach
main, meldet gcc:implicit declaration of function 'summe'.
Programme auf Dateien verteilen
Größere Programme teilt man auf mehrere Dateien auf — z. B. ein Modul rechner mit Rechenfunktionen und ein Hauptprogramm:
- Header rechner.h:enthält nur die Prototypen — die „Speisekarte“ des Moduls.
- rechner.c:enthält die Definitionen, also die Funktionsrümpfe.
- main.c:enthält
mainund ruft die Funktionen auf. - #include "…":Anführungszeichen: eigene Datei im Projektordner;
<…>: Systembibliothek. - Include-Guard:
#ifndef RECHNER_H/#define RECHNER_H…#endifverhindert, dass der Header doppelt eingefügt wird. - Übersetzen:alle .c-Dateien angeben, nie die .h-Datei:
gcc main.c rechner.c -o rechner.
Zerlege das Programm programm.c in Bausteine und lege sie auf die drei Dateien um: Ziehe einen Baustein in eine Datei — oder wähle ihn mit Enter, suche das Ziel mit den Pfeiltasten und lege ihn mit Enter ab. Prüfen vergleicht mit der üblichen Aufteilung, Übersetzen zeigt, was gcc dazu sagt.
$
Halte fest: In die Header-Datei gehören nur die Ankündigungen (Prototypen), eingerahmt vom Include-Guard; die Definitionen stehen in genau einer .c-Datei. Jede .c-Datei, die die Funktionen benutzt oder definiert, bindet den Header mit #include "rechner.h" ein.
$ gcc main.c rechner.c -o rechner $ ./rechner 49 9 5.5
Aufteilen: Prototypen in die .h-Datei (mit Include-Guard), Definitionen in die .c-Datei, einbinden mit #include "name.h", übersetzen mit gcc main.c name.c -o prog.
Allgemeine Hinweise
Semikolon nur beim Prototyp
int summe(int a, int b); kündigt an. Steht bei der Definition ein ; vor {, meldet gcc einen Syntaxfehler.
Keine Definitionen im Header
Bindet man einen Header mit Funktionsrümpfen in zwei .c-Dateien ein, meldet der Linker multiple definition.
Rückgabewert nutzen
Eine Funktion mit int liefert einen Wert — speichere ihn oder gib ihn aus, sonst geht das Ergebnis verloren.
