ProgrammierungSystemprogrammierer

Erläutern Sie die Besonderheiten der Deklaration und Verwendung von Funktionszeigern in C. Wie speichert man korrekt ein Array von Zeigern auf verschiedene Funktionen und ruft sie dynamisch auf?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

Ein Funktionszeiger in C ist eine Variable, die die Adresse einer Funktion speichert und es ermöglicht, dynamisch auszuwählen, welche Funktion aufgerufen werden soll. Die übliche Deklaration eines Funktionszeigers lautet:

// Funktionszeiger, der ein int entgegennimmt und ein int zurückgibt int (*f_ptr)(int);

Für ein Array von Zeigern:

int func1(int x) { return x + 1; } int func2(int x) { return x * 2; } int (*f_arr[2])(int) = { func1, func2 }; int result = f_arr[1](10); // gibt 20 zurück
  • Dieser Ansatz ermöglicht die Erstellung von Befehltabellen, Handlern oder das automatische Verknüpfen von Aktionen mit einer Operationsnummer.
  • Alle Funktionen müssen die gleiche Signatur haben.
  • Bei der Arbeit mit Funktionszeigern müssen die Typen genau übereinstimmen.

Fangfrage

Kann man mit Hilfe eines Funktionszeigers eine Funktion mit einer anderen Signatur aufrufen?

Häufig falsche Antwort: „Ja, wenn man Typumwandlung verwendet.“

Richtige Antwort: Technisch ist das möglich aufgrund der dynamischen Natur von Zeigern, aber eine solche Aktion führt zu Runtime-Fehlern und unvorhersehbarem Verhalten, da Funktionen mit unterschiedlichen Aufruf- und Argumentkonventionen aufgerufen werden.

Beispiel:

void funcA(int x) { printf("A: %d\n", x); } void funcB(float y) { printf("B: %f\n", y); } void (*fptr)(int) = (void (*)(int)) funcB; fptr(5); // FEHLER: falsche Daten werden übergeben

Beispiele für reale Fehler aufgrund fehlender Kenntnisse zu diesem Thema


Geschichte

In einem Plugin-System wurden in einer Tabelle von Zeigern Funktionen mit unterschiedlichen Signaturen abgelegt (eine gab int zurück, die andere void). Beim Start auf einigen Architekturen kam es zu Stapelbeschädigungen.

Geschichte

In einem alten System zur Befehlsverwaltung verwendeten sie ein Array von Funktionszeigern. Ein Neuer fügte eine Funktion mit zusätzlichen Parametern hinzu, was zu unvorhersehbarem Verhalten nach dem Wechsel zu einem neuen Array-Element führte.

Geschichte

In der Firmware wurde das Ergebnis eines Zeigerwechsels auf Funktionen nicht überprüft. Eine unzureichende Initialisierung des Handler-Arrays führte zum Aufruf eines Nullzeigers (NULL), woraufhin das Gerät ohne Benachrichtigung des Benutzers hängen blieb.