Juhuuu, mal wieder Funktionszeiger !
-
Hi!
Einem void* Zeiger kann man ja bekanntlich zur Laufzeit verschiedene Datentypen zuweisen.
Geht so etwas auch mit Funktionen ? Oder bleibe ich da vor Unionen nicht verschont ?
Ich möchte gern einem Zeiger zur Laufzeit verschiedene Funktionen mit zuweisen.
Möglicherweise geht das aber auch gar nicht.
Hab sowas jedenfalls noch nicht gesehen.
Also ich habe mir so etwas in der Art gedacht( was leider nicht funzt):void *fp; fp = pow; // warning nonstandard extension, function/data pointer conversion in expression fp(1.0,2.0); // error 'fp' : not a function fp = abs; // warning nonstandard extension, function/data pointer conversion in expression fp(-1); // error 'fp' : not a function // auch mit überredungskünsten wie casten ist da nix zu machen (double(*)(double,double))fp(1.0,2.0); // error 'fp' : not a function (int (*)(int)) fp(-1); // error 'fp' : not a function
So etwas wie einen
(...)(*magic_funct_ptr)(...)
gibts wohl nicht
Bleiben nur noch Unionen, ne.
gruß
p.n.
-
...oder ein
void*
Parameter, der auf einestruct
mit Parametern zeigt.greetz, Swordfish
-
Das primitivste Beispiel sieht in etwa so aus:
// Funktionskette struct registered_function { void (*functionpointer) (void); struct registered_function *next_function; }; unsigned int registered_functions = 0; static struct registered_function *first_function = NULL; static struct registered_function *last_function = NULL; // ------------------------------------------------------------------------------------------- // Funktion eintragen unsigned int AddFunction( void (*function) (void) ) { struct registered_function *new_function = malloc(sizeof(struct registered_function)); if (new_function) { new_function->functionpointer = function; new_function->next_function = NULL; if (registered_functions) last_function->next_function = new_function; else first_function = new_function; last_function = new_function; registered_functions++; return registered_functions; } else return 0; } // ------------------------------------------------------------------------------------------- // Funktion irgendwann ausführen void DoFunctions(void) { struct registered_function *counter; // void (*ptr) (void); Kette von void- Funktionen if (registered_functions) { counter = first_function; while (counter) { (*counter->functionpointer)(); counter = counter->next_function; } } }
Wenn Du in der Struct noch einen Union- Block reinsetzt, der die Argumente mitträgt und den Funktionspointer auf void * castest (folglich auch in der struct statt des Funktionspointers einen void* anlegst), hast Du's fast. Dann kannst Du beliebige Funktionspointer auf die eigene struct loslassen, aber Vorsicht
Ein klitzekleiner Fehler und das Konstrukt geht komplett krachen!
-
pointer n00b schrieb:
void *fp; fp = pow; // warning nonstandard extension, function/data pointer conversion in expression fp(1.0,2.0); // error 'fp' : not a function fp = abs; // warning nonstandard extension, function/data pointer conversion in expression fp(-1); // error 'fp' : not a function // auch mit überredungskünsten wie casten ist da nix zu machen (double(*)(double,double))fp(1.0,2.0); // error 'fp' : not a function (int (*)(int)) fp(-1); // error 'fp' : not a function
Alles nur eine Frage des Vorrangs von Operatoren:
((double(*)(double,double))fp)(1.0,2.0); ((int(*)(int))fp)(-1);
Natürlich abgesehen von den prinzipiellen Problemen dieser Konvertierung.
-
@pointercrash()
so in der art wird es tatsächlich ablaufen, bloss das ich mir einen strkuturblock am stück hole und mit einem einfachen index-operator drüber wandere.camper schrieb:
Alles nur eine Frage des Vorrangs von Operatoren:
((double(*)(double,double))fp)(1.0,2.0); ((int(*)(int))fp)(-1);
Natürlich abgesehen von den prinzipiellen Problemen dieser Konvertierung.
der compiler meckert zwar immer noch:
warning: nonstandard extension, function/data pointer conversion in expression
warning: 'type cast' : from data pointer 'void *' to function pointer 'double (__cdecl *)(double ,double )'aber es funktionert jetzt jedenfalls.
was für konvertierungsprobleme meinst du ? mit was für problemen muss ich rechnen ?
ausser das ich irgendwo speichern muss, welcher voidzeiger welchen funktionstypen hat sehe ich keine schwierigkeiten.
-
pointer experienced schrieb:
mit was für problemen muss ich rechnen ?
ausser das ich irgendwo speichern muss, welcher voidzeiger welchen funktionstypen hat sehe ich keine schwierigkeiten.Du hast es hiermit selbst beantwortet - der Compiler gibt ja seine warning nicht zum Spaß aus.
Mit dem void* cast entziehst Du ihm die Überwachung der Typenrichtigkeit zur Compiletime, weshalb Du zur Runtime sicherstellen mußt, daß der Pointer richtig aufgelöst wird. Du wirst selber merken, daß sich bei solchen Konstrukten eingeschlichene Fehler nur schlecht finden lassen und Pointer, die "irgendwas" sind und nur an bestimmten Stellen eine bestimmte Bedeutung bekommen, als "leseunfreundlich" gelten.Sofern anders lösbar, solltest Du insbesondere das Pointercasting lassen - ist zwar jetzt nicht unbedingt meine Meinung, aber so ähnlich äußern sich die C-Puristen.
-
pointercrash() schrieb:
Sofern anders lösbar, solltest Du insbesondere das Pointercasting lassen - ist zwar jetzt nicht unbedingt meine Meinung, aber so ähnlich äußern sich die C-Puristen.
ja, es ist anders lösbar, ich könnte eine union innerhalb einer struktur benutzen und in der struktur den funktionstyp speichern.
allerdings kann ich die union nicht so bequem wie eine struktur initialisieren, sondern brauche eine initialisierungs-funktion.
dann ist aber wenigstens das meckern des compilers weg.
so sollte ich es vielleicht machen.