Ich habe einen PIC18F46K22 und programmiere ihn mit dem XC8-Compiler. Am Ende habe ich ein System wie ein PC mit stdin
und stdout
. In der Hauptschleife gibt es also eine Funktion, die prüft, ob es neue Eingaben gibt. Wenn eine Eingabe vorhanden ist, wird eine entsprechende Funktion aufgerufen. Wenn ich also zum Beispiel ein A stdin
eingebe, führt der PIC eine Funktion wie function_A
aus function_B
, die aufgerufen wird, wenn ich ein B eingebe.
Wenn der PIC mit der Funktion fertig ist, möchte ich, dass die neue Eingabe an die Funktion gesendet wird. Wenn also A gedrückt wird, öffnet sich der RS232-Sender, von diesem Moment an wird jede Eingabe über RS232 gesendet. Am Ende ist das Projekt ein eigenständiger Texteditor. Wenn Sie also A drücken, wird das Dateisystem geöffnet. Von diesem Moment an bearbeiten Sie keinen Text mehr, sondern sehen sich eine Liste von Dateien an. Das bedeutet, dass das Drücken von Auf und Ab etwas anderes bedeutet als in der Textbearbeitungsumgebung.
Ich habe viel darüber nachgedacht, wie ich das in C programmieren kann. Ich habe mir das letzte Nacht ausgedacht und würde gerne wissen, ob es möglich ist und wenn ja, wie. Was ich tun möchte, ist:
main
Funktion ruft eine Funktion wie auffunction_A
function_A
ändert eine globale Variable function_addr
in den Adresszeiger der Funktionin_function_A
main
die Funktion auf , function_addr
wenn eine neue Eingabe vorliegt.Was ich also brauchen würde, ist eine main
Funktion, die prüft, ob function_addr
Null ist. Wenn dies der Fall ist, sollte eine "normale" Funktion aufgerufen werden, z. B. function_A
. Ist dies nicht der Fall, function_addr
sollte die Funktion at aufgerufen werden. Ich brauche auch einen function_A
, der den function_addr
in einen Zeiger auf ändert in_function_A
.
Hinweis: Wenn die Dateisystemfunktion geschlossen werden soll, is_function_A
sollte sie einfach function_addr
auf 0 geändert werden.
Also im Grunde ist meine Frage, wie kann ich
Eine Funktion
int f(int x){ .. }
Holen Sie sich die Adresse einer Funktion (und speichern Sie sie in einer Variablen)
int (*fp)(int) = f;
Rufen Sie eine Funktion an einer angegebenen Adresse auf
int x = (*fp)( 12 );
fp(12)
erhöht nicht die Lesbarkeit über (*fp)(12)
. Sie haben eine unterschiedliche Lesbarkeit. (*fp)(12)
erinnert den Leser daran, dass fp
es sich um einen Zeiger handelt, und ähnelt auch der Deklaration von fp
. Meiner Meinung nach ist dieser Stil mit alten Quellen wie X11-Interna und K&R C verbunden. Ein möglicher Grund, warum er mit K&R C verbunden sein könnte, ist, dass es in ANSI C möglich ist, fp
mithilfe der Funktionssyntax zu deklarieren, ob fp
ein Parameter ist: int func(int fp(double)) {}
. Bei K&R C wäre das gewesen int func(fp) int (*fp)(double); { ... }
.Während Wouters Antwort absolut richtig ist, ist dies vielleicht anfängerfreundlicher und ein besseres Beispiel für Ihre Frage.
int (*fp)(int) = NULL;
int FunctionA(int x){
return x + x;
}
int FunctionB(int x){
return x * x;
}
void Example(void) {
int x = 0;
fp = FunctionA;
x = fp(3); /* after this, x == 6 */
fp = FunctionB;
x = fp(3); /* after this, x == 9 */
}
Wenn es nicht offensichtlich ist, dass dem Funktionszeiger tatsächlich eine Zielfunktionsadresse zugewiesen ist, ist es ratsam, eine NULL-Prüfung durchzuführen.
if (fp != NULL)
fp(); /* with parameters, if applicable */
fp
zufällig belegt wird, anfänglich tatsächlich NULL ist. Ich würde es int (*fp)(int) = NULL;
als kombinierte Deklaration und Initialisierung tun, um sicher zu sein - Sie möchten nicht zu einem zufälligen Speicherort springen, weil ein alberner Wert zufällig dort war. Dann weisen Sie einfach fp
like in Ihrer Example()
Funktion zu.fp
es sich um eine "globale Variable" handelt (wie im obigen Code), wird sie garantiert initialisiert NULL
(ohne dies explizit tun zu müssen).
Benutzer207421
Adam Lawrence
Kortuk
Kaz
Benutzer207421
Benutzer17592
davidcary