C Forever

C : Interna - Funktionen

In C gibt es nur eine einzige Art von Funktion.
Sie ist folgendermaßen definiert :

return-type function-name( argument declarations )
    {
    declarations and statements
    }

Wichtig ist hier :

"Nested", also verschachtelte Funktionen, wie sie in einigen anderen Programmiersprachen möglich sind, sind in C NICHT erlaubt.

Weiter will ich erstmal nicht auf spezielle Eigenschaften von Funktionen eingehen. Das hole ich später nach, versprochen!

Fehler und ihre Behandlung

In Funktionen (wie im gesamten Programm auch) werden Bedingungen auftreten, die zur Laufzeit einen Fehler provozieren. So etwas kann entweder in der Funktion abgefangen und behandelt werden oder muss nach außerhalb der Funktion kommuniziert werden.

Zur Anzeige eines Fehlers wird dem aufrufenden Programm ein entsprechender Rückgabewert zur Verfügung gestellt. Und hier beginnt das Drama!

Erste Erkenntnis

Es ist unabdingbar notwendig, den Rückgabewert jeder Funktion auszuwerten. Dabei darf man sich NICHT darauf verlassen, daß der Rückgabewert normal weiterverwendet werden kann, er kann ja auch einen Fehler signalisieren. Das ist normalerweise ein Wert, der im Zusammenhang mit der Funktion eine Weiterverarbeitung sinnlos macht und dadurch zu unerwartetem Verhalten führt. Unter Umständen resultiert daraus sogar ein Absturz des Programms.

Zweite Erkenntnis

Es kann durchaus sinnvoll sein, den Rückgabewert einer Funktion ausschließlich zum Signalisieren eines Fehlerszustands einzusetzen. Das Ergebnis der Funktion wird dann über eine Zeigervariable (Referenz) zurückgegeben.

Dritte Erkenntnis

Das Interface einer Funktion ist unbedingt vollständig und sorgfältig zu dokumentieren! Nur so lassen sich Fehler bei der Verwendung wenigstens ansatzweise verhindern.

Variable Parameter-Liste

Hier geht es um etwas, das besonders aus der printf-Funktion bekannt ist : Implementieren und Aufruf einer Funktion mit einer Liste von Parametern, von der weder die Anzahl der Parameter noch deren Typ bekannt ist.

Eigentlich scheint das in "C" ja nicht vorgesehen zu sein - ist es auch nicht. In der C-Standard-Bibliothek hat man sich aber die Mühe gemacht, dafür eine Schnittstelle zu implementieren.

Die folgende Funktion ist nur ein Beispiel, wichtig darin sind die Aufrufparameter und der Umgang damit.

#include <stdarg.h>

void function( int first, ... )
    {
    double second;
    char third;
    long int * p_forth;
    va_list arg_list;

    va_start(arg_list, first);

    second = va_arg(arg_list, double);
    third = va_arg(arg_list, char);
    p_forth = va_arg(arg_list, long int *);

    va_end(arg_list);
    }

Die drei Punkte ... bezeichnen die in Typ und Anzahl variablen Parameter. Davor muss mindestes ein Parameter mit Name und Typ angegeben sein.
Für die weitere Verarbeitung der unbekannten Parameter sind ein Typ und drei Makros verantwortlich, die in der HeaderDatei stdarg.h definiert sind :

va_list

In einer Variable vom Typ va_list wird die Liste der unbekannten Parameter verwaltet. Sie muss natürlich vor dem Zugriff auf diese deklariert sein.

va_start()

Dieses Makro wird mit der Variablen vom Typ va_list und dem letzten namentlich deklarierten Parameter aufgerufen.
Es setzt den Zeiger in der Liste auf den ersten Parameter der mit den drei Punkten umschriebenen Liste.

va_arg()

Jeder Aufruf von va_arg() gibt einen Wert des angegebenen Typs zurück und schiebt dann der Zeiger in der Liste zum nächsten Parameter.
Der Programmierer ist selbst verantwortlich dafür, daß nicht mehr Parameter aus der Liste abgeholt werden, als sich darin befinden, und daß der Typ des Parameters in der Liste mit dem Typ der Zielvariable übereinstimmt.

va_end()

Dieses letzte Makro gibt die Parameter-Liste wieder frei. Die Variable ist anschließend undefiniert.

Hinweise

Zwei Hinweise zu dieser kurzen Beschreibung des Themas will ich hier noch geben :

  1. Die Abfolge der Aufrufe va_start() ... va_arg() ... va_arg() ... va_end() kann beliebig oft wiederholt werden. So ist es möglich die Liste der Parameter nicht nur einmal zu durchlaufen.
  2. Es ist sehr zu empfehlen, sich die Manpage zu den genannten Funktionen sorgfältig durchzulesen, z.B. im Webbrowser nach "man va_start" suchen (für Linux z.B. gibt es eine hier).
    Sie beschreibt die Möglichkeiten und Fallstricke dieser Funktionalität wesentlich besser und ausführicher als mein kurzer Überblick.
© Uwe Jantzen 13.12.23