Zeiger und Speicher

Funktionszeiger und Callbacks in C und C++

In dieser Lektion übergibst du eine Funktion als Parameter an eine andere Funktion, mit Funktionszeigern in C und Lambdas in C++.

Einführung

Ein Callback ist die Technik, einer Funktion eine andere Funktion zu übergeben, die sie bei Bedarf zurückruft. So kann ein allgemeiner Algorithmus das von der aufrufenden Stelle gewählte Verhalten ausführen, ohne Details der Umsetzung zu kennen. Dieselbe Funktion apply kann zum Beispiel quadrieren, verdoppeln oder jede andere Umwandlung durchführen.

Wichtige Punkte

  • Ein Zeiger darf nur auf ein noch existierendes Objekt des richtigen Typs zeigen oder null sein.
  • Jeder reservierte Speicherbereich muss genau einmal freigegeben werden.
  • Mache deutlich, welche Funktion den Speicher besitzt (ownership) und welche Daten nur gelesen werden (const).

Codebeispiele in C und C++

C
Code ausführen →
main.c
#include <stdio.h>

int square(int value) { return value * value; }
int apply(int value, int (*operation)(int)) { return operation(value); }

int main(void) {
    printf("%d\n", apply(6, square));
    return 0;
}
Ergebnis der Ausführung
36
C++
Code ausführen →
main.cpp
#include <functional>
#include <iostream>

int apply(int value, const std::function<int(int)>& operation) {
    return operation(value);
}

int main() {
    int factor = 6;
    std::cout << apply(factor, [](int value) { return value * value; }) << '\n';
}
Ergebnis der Ausführung
36

C und C++ im Vergleich

In C ist der Parameter int (*operation)(int) ein Funktionszeiger, der Funktionen mit einem int-Parameter und int-Rückgabewert annimmt, deshalb gibt apply(6, square) den Wert 36 zurück. In C++ können Lambdas und std::function eine größere Vielfalt aufrufbarer Objekte (callables) speichern. Bei leistungskritischem Code sind Templates oft die bessere Wahl als std::function.

C

Besitz und Freigabe von Speicher muss der Programmierer vollständig selbst sicherstellen.

C++

Container und RAII geben Ressourcen automatisch frei, wenn die Lebensdauer des Objekts endet.

Übungen zur Vertiefung

Führe beide Versionen aus und ändere dann den Code, um zu beobachten, welche Sicherheit jede Sprache bietet.

  • Teste mit Nullzeigern und fehlgeschlagener Speicherreservierung.
  • Führe das Programm mit AddressSanitizer und UndefinedBehaviorSanitizer aus, um Speicherfehler zu finden.
  • Notiere klar, welcher Zeiger den Speicher besitzt und welcher nur zum Lesen dient.

Mit einer Challenge üben

Nutze den Inhalt dieser Lektion, um ein echtes Problem zu lösen. Jede Challenge läuft im Browser, mit sofortigen Tests und einem KI-Review.

Alle Challenges