1 Theorie | |
→ | 1.1 Die Programmiersprache C |
Zeiger auf Funktionen | |
Funktionen im Hauptspeicher | |
Typdefinition für Funktionen | |
Funktionszeiger ohne Verwendung einer Typdefinition | |
Callback-Funktion |
Im Hauptspeicher befinden sich nicht nur die Variablen des Programmes, sondern auch der auszuführende Maschinencode. Für jede Funktion gibt es eine Adresse im Hauptspeicher, an der der entsprechende Maschinencode beginnt.
Ein Funktionstyp kann mit typedef definiert werden wie
ein Prototyp einer Funktion, dabei wird anstelle des
Funktionsnamens der Typname angegeben. Weiterhin wird der
Rückgabetyp der Funktion angegeben und der Typ der Argumente.
Beispielsweise definiert
typedef int text_compare_fct(const char *, const char *);
einen Typ von Funktionen mit derselben Signatur (gleicher Rückgabetyp und gleiche Argumentetypen) wie die bereits vorhandenen Funktionen
int strcmp(const char *s1, const char *s2); /* Unter Windows mit VStudio _stricmp, auf anderen Systemen strcasecmp. */ int _stricmp(const char *s1, const char *s2);
Im Beispiel ex084 wird diese Typdefinition in der main()-Funktion benutzt, um eine Zeigervariable fctptr anzulegen, in der Adressen von Funktionen dieses Typs gespeichert werden können.
Wird der Name einer bereits definierten Funktion im Quelltext benutzt, ohne dass darauf die für den Funktionsaufruf typischen Klammern folgen, liefert dieser reine Funktionsname die Adresse der entsprechenden Funktion.
Dies wird im Beispiel benutzt, um die Zeigervariable einmal auf die Adresse von strcmp() und einmal auf die Adresse von _stricmp() zu setzen. Anschließend werden die Funktionen über Verwendung des Zeigers aufgerufen und das Ergebnis zwischengespeichert und ausgegeben.
/* Beispiel ex084.c: Verwendung von Zeigern auf Funktionen.
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Konstanter Text auf linker Seite des Vergleiches.
*/
const char str1[] = { "Das ist ein Test." };
/* Konstanter Text auf rechter Seite des Vergleiches.
*/
const char str2[] = { "DIES IST EIN TEST." };
/* Typ von Vergleichsfunktionen:
Die Vergleichsfunktionen bekommen zwei Zeiger auf konstante
char-Felder und geben einen int-Wert fuer das Vergleichsergebnis
zurueck. Dieser ist positiv wenn der linke String "groesser" ist
als der rechte, 0 wenn beide Strings gleich bewertet werden
und negativ wenn der linke String "kleiner" ist als der rechte.
*/
typedef
int
text_compare_fct(const char *, const char *);
int
main(void)
{
text_compare_fct *fctptr; /* Zeiger auf eine Vergleichsfunktion */
int i; /* Vergleichsergebnis */
/* Zeiger auf Adresse der Funktion strcmp setzen.
*/
fctptr = strcmp;
/* Bildschirmausgabe, mit welcher Funktion der Vergleich erfolgt.
*/
printf("Vergleich \"%s\" und \"%s\" mit strcmp\n", str1, str2);
/* Zeiger dereferenzieren und Funktion aufrufen, Ergebnis speichern.
*/
i = (*fctptr)(str1, str2);
/* Ergebnis ausgeben.
*/
printf("Ergebnis: %d\n\n", i);
/* Jetzt _stricmp verwenden (auf Nicht-Windows-Systemen strcasecmp).
*/
fctptr = _stricmp;
printf("Vergleich \"%s\" und \"%s\" mit _stricmp\n", str1, str2);
i = (*fctptr)(str1, str2);
printf("Ergebnis: %d\n\n", i);
return EXIT_SUCCESS;
}
/* vim: set ai sw=4 ts=4 : */
Beispiel ex085 führt dieselbe Funktionalität aus wie Beispiel ex084, allerdings wurde hier die typedef-Definition eingespart.
Zeile 21
int (*fctptr)(const char *, const char *);
hat dabei folgende Bedeutung:
/* Beispiel ex085.c: Verwendung von Zeigern auf Funktionen.
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Konstanter Text auf linker Seite des Vergleiches.
*/
const char str1[] = { "Das ist ein Test." };
/* Konstanter Text auf rechter Seite des Vergleiches.
*/
const char str2[] = { "DIES IST EIN TEST." };
int
main(void)
{
int (*fctptr)(const char *, const char *); /* Zeiger auf eine Vergleichsfunktion */
int i; /* Vergleichsergebnis */
/* Funktion strcmp verwenden.
*/
fctptr = strcmp;
printf("Vergleich \"%s\" und \"%s\" mit strcmp\n", str1, str2);
i = (*fctptr)(str1, str2);
printf("Ergebnis: %d\n\n", i);
/* Funktion _stricmp verwenden.
*/
fctptr = _stricmp;
printf("Vergleich \"%s\" und \"%s\" mit _stricmp\n", str1, str2);
i = (*fctptr)(str1, str2);
printf("Ergebnis: %d\n\n", i);
return EXIT_SUCCESS;
}
/* vim: set ai sw=4 ts=4 : */
Erhält eine Funktion als Argument einen Zeiger auf eine andere
Funktion, um diese Funktion über den Zeiger aufzurufen, wird die
aufgerufene Funktion als Callback-Funktion bezeichnet.
Im Beispiel ex086 werden strcmp() und _stricmp() als
Callback-Funktionen verwendet, die von der Funktion
vergleichen_und_ausgeben() aufgerufen werden.
/* Beispiel ex086.c: Verwendung von Zeigern auf Funktionen.
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Konstanter Text auf linker Seite des Vergleiches.
*/
const char str1[] = { "Das ist ein Test." };
/* Konstanter Text auf rechter Seite des Vergleiches.
*/
const char str2[] = { "DIES IST EIN TEST." };
/* Vergleichen zweier Strings und Ausgabe des Ergebnisses.
Das dritte Argument ist ein Zeiger auf eine Funktion, die zwei
Zeiger auf konstante Felder mit Zeichen als Argument erhaelt
und einen int-Wert zurueckgibt.
*/
void
vergleichen_und_ausgeben(
const char *s1,
const char *s2,
int (*vergleichsfunktion)(const char *, const char *)
)
{
int i; /* Vergleichsergebnis */
printf("Vergleich von \"%s\" und \"%s\"\n", s1, s2);
i = (*vergleichsfunktion)(s1, s2);
printf("Ergebnis: %d\n\n", i);
}
int
main(void)
{
printf("Vergleich mit strcmp\n");
vergleichen_und_ausgeben(str1, str2, strcmp);
printf("Vergleich mit _strcimp\n");
vergleichen_und_ausgeben(str1, str2, _stricmp);
return EXIT_SUCCESS;
}
/* vim: set ai sw=4 ts=4 : */