Eine Funktion fasst Anweisungen zu einem benannten Baustein zusammen.
#include <stdio.h>
int addiere(int a, int b) {
return a + b;
}
void gruss(const char *name) {
printf("Hallo %s!\n", name);
}
double mittelwert(double a, double b) { return (a + b) / 2; }
int main(void) {
printf("%d\n", addiere(3, 4));
gruss("Mia");
printf("%.1f\n", mittelwert(3, 4));
return 0;
}7 Hallo Mia! 3.5
Aufbau: Rückgabetyp name(Parameter) { ... return wert; }. void heißt "kein Rückgabewert". main(void) bedeutet "keine Parameter" (() allein hieße in C: "unbekannt").
Argumente werden kopiert (call by value)
C übergibt alles als Kopie. Eine Funktion kann Variablen des Aufrufers nur ändern, wenn du ihr die Adresse (einen Zeiger) gibst:
#include <stdio.h>
void falsch(int x) { x = 99; } // ändert nur die Kopie
void richtig(int *x) { *x = 99; } // ändert das Original
void tausche(int *a, int *b) { int t = *a; *a = *b; *b = t; }
int main(void) {
int n = 1;
falsch(n);
printf("%d\n", n);
richtig(&n);
printf("%d\n", n);
int a = 1, b = 2;
tausche(&a, &b);
printf("%d %d\n", a, b);
return 0;
}1 99 2 1
Zeiger lernst du im übernächsten Kapitel genauer kennen.
Mehrere Ergebnisse zurückgeben
Mit Zeigern als "Ausgabeparameter" oder mit einer Struktur:
#include <stdio.h>
void minMax(const int *a, int n, int *min, int *max) {
*min = *max = a[0];
for (int i = 1; i < n; i++) {
if (a[i] < *min) *min = a[i];
if (a[i] > *max) *max = a[i];
}
}
typedef struct { int min, max; } Bereich;
Bereich bereich(const int *a, int n) {
Bereich b = { a[0], a[0] };
for (int i = 1; i < n; i++) { if (a[i] < b.min) b.min = a[i]; if (a[i] > b.max) b.max = a[i]; }
return b;
}
int main(void) {
int z[] = {5, 3, 9, 1, 7};
int mi, ma;
minMax(z, 5, &mi, &ma);
printf("%d %d\n", mi, ma);
Bereich b = bereich(z, 5);
printf("%d %d\n", b.min, b.max);
return 0;
}1 9 1 9
Rekursion
#include <stdio.h>
long fakultaet(int n) { return n <= 1 ? 1 : n * fakultaet(n - 1); }
int ggt(int a, int b) { return b == 0 ? a : ggt(b, a % b); }
void binaer(unsigned n) { if (n > 1) binaer(n / 2); putchar('0' + n % 2); }
int main(void) {
printf("%ld %ld\n", fakultaet(10), fakultaet(20));
printf("%d\n", ggt(48, 18));
binaer(42); putchar('\n');
return 0;
}3628800 2432902008176640000 6 101010
Jede Rekursion braucht eine Abbruchbedingung. Zu tiefe Rekursion füllt den Stack (Absturz mit "Stack overflow").
static und inline
staticbei einer Funktion: nur in dieser Datei sichtbar (interne Verknüpfung)staticbei einer lokalen Variable: behält den Wert zwischen Aufrufeninlineist ein Hinweis an den Compiler, den Funktionsrumpf einzusetzen
Funktionszeiger
Funktionen haben eine Adresse, und man kann sie in Variablen speichern und übergeben. So funktionieren Rückrufe (Callbacks), zum Beispiel bei qsort:
#include <stdio.h>
#include <stdlib.h>
static int vergleiche(const void *a, const void *b) {
int x = *(const int *) a, y = *(const int *) b;
return (x > y) - (x < y);
}
int plus(int a, int b) { return a + b; }
int mal(int a, int b) { return a * b; }
int wende(int (*f)(int, int), int a, int b) { return f(a, b); }
int main(void) {
int z[] = {5, 3, 9, 1, 7};
qsort(z, 5, sizeof z[0], vergleiche);
for (int i = 0; i < 5; i++) printf("%d ", z[i]);
printf("\n");
printf("%d %d\n", wende(plus, 3, 4), wende(mal, 3, 4));
int (*op)(int, int) = mal;
printf("%d\n", op(6, 7));
return 0;
}1 3 5 7 9 7 12 42
Variable Argumentlisten
printf kann beliebig viele Argumente. Eigene Funktionen schreibst du mit <stdarg.h>:
#include <stdio.h>
#include <stdarg.h>
int summe(int anzahl, ...) {
va_list args;
va_start(args, anzahl);
int s = 0;
for (int i = 0; i < anzahl; i++) s += va_arg(args, int);
va_end(args);
return s;
}
int main(void) {
printf("%d %d\n", summe(3, 1, 2, 3), summe(5, 10, 20, 30, 40, 50));
return 0;
}6 150
Merke
Rückgabetyp name(Parameter);voidfür "nichts"- Argumente werden kopiert; für Änderungen übergibst du Zeiger (
&x,*p) - Mehrere Ergebnisse: Zeiger oder
struct - Rekursion braucht eine Abbruchbedingung
- Funktionszeiger ermöglichen Callbacks (
qsort) staticbei Funktionen macht sie dateilokal
Aufgabe
Schreibe potenz(basis, exp) einmal mit Schleife und einmal rekursiv sowie eine Funktion, die ein Array der Größe nach sortiert (mit qsort).