Das heißt, ich will die Funktion "check" später z.B. in der Art aufrufen
können:
1
check(func1(08, 15))
...oder so ähnlich.
Klar könnte ich einen Funktionspointer nehmen, müsste dann aber "check"
alle Parameter von "funcX" übergeben.
Gibt es in C vielleicht eine elegantere Lösung?
Vielen Dank,
Erik
> Das heißt, ich will die Funktion "check" später z.B. in der Art aufrufen> können:>
1
check(func1(08, 15))
> ...oder so ähnlich.> Klar könnte ich einen Funktionspointer nehmen, müsste dann aber "check"> alle Parameter von "funcX" übergeben.
Irgendwie müssen die Argumente aber bis zum Aufruf der
eigentlichen Funktionen durchkommen.
* Entweder du gibst die Argumente geimeinsam mit dem Funktionspointer
an check
* check holt sich die Argumente irgendwo her (globale Variablen oder
vielleicht kommen die ja auch aus einer Berechnung)
* Du änderst die auzurufenden Funktionen so ab, dass sie keine
Argumente mehr haben wollen
Wenn es dir nur darum geht, dass es ein paar Funktionen
gibt, die einen Fehlercode zurückliefern und du deine
Funktion machen möchtest, die den Fehlercode auswertet,
was spricht dann dagegen, das genau so zu implementieren:
void check( unsigned char FehlerCode )
{
if( FehlerCode == irgendwas )
mach was
else
mach was anderes
}
und das dann so zu benutzen
check( func1( 08, 15 ) );
die Funktion func1 wird mit ihren Argumenten 08 und 15 aufgerufen
und liefert als Ergebnis einen Fehlercode, dieser retournierte
Fehlercode wird an die Funktion check weitergereicht, die ihn
dann auswertet.
@Karl heinz Buchegger
Zunächst mal Danke!
>void check( unsigned char FehlerCode )
Das man das machen kann ist klar. Je nach Schweregrad des Fehlers soll
"check" selbst aber versuchen evtl. "funcX" nochmals aufzurufen. Wenns
dann immer nach nicht geklappt hat, wird kapituliert oder so...
"check" einen Funktionspointer und dann nochmals sämtliche Parameter der
"gepointerten" Funktion zu übergeben wollte ich vermeinden. Ich werde es
dann aber eben so machen, wenn es nicht anders geht.
Ich dachte nur, es ginge vielleicht, einen Funktionspointer INKL.
Parameter zu erstellen und aufzurufen, da ja "eigentlich nur" die Daten
auf dem Stack abgearbeitet werden müssen...
Gruß, Erik
> "check" einen Funktionspointer und dann nochmals sämtliche Parameter der> "gepointerten" Funktion zu übergeben wollte ich vermeinden. Ich werde es> dann aber eben so machen, wenn es nicht anders geht.
Was mir daran noch nicht gefällt, ist das die Parameter dann ja 2mal auf
dem Stack landen. Einmal bei der Übergabe an "check" und nochmal beim
Aufruf der Funktion auf die der Pointer zeigt.
@A.K.
> in C wird es umständlich
Wie umständlich ist umständlich denn :-) ?
Danke,
Erik
Erik wrote:
>> in C wird es umständlich> Wie umständlich ist umständlich denn :-) ?
Ziemlich.
Eine Möglichkeit wäre es, für Funktion und Argumente eine
struct zu bauen.
struct CallFunc
{
FuncPtr theFunction;
uint8_t Argument1;
uint8_t Argument2;
};
beim Aufrufer wird die Struktur ausgefüllt und so ein Objekt
an check übergeben.
In C++ geht das wunderbar, weil es dort Konstruktoren gibt,
die so ein Objekt 'on the fly' erzeugen und initialisieren
können:
struct CallFunc
{
CallFunc( FuncPtr A, uint8_t B, uint8_t C ) :
theFunction( A ), Argument1( B ), Argument2( C )
{}
FuncPtr theFunction;
uint8_t Argument1;
uint8_t Argument2;
};
Damit ist dann möglich:
check( CallFunc( Function1, 08, 15 ) );
In C gibt es das aber nicht, und dann wirds unhandlich:
struct CallFunc Arg;
Arg.theFunction = Function1;
Arg.Argument1 = 08;
Arg.Argument2 = 15;
check( &Arg );
Ah. Man könnte sich mit einer Hilfsfunktion behelfen:
struct CallFunc* CreateObj( FuncPtr A, uint8_t B, uint8_t C )
{
struct CallFunc* pNew = malloc( sizeof struct CallFunc );
pNew->theFunction = A;
pNew->Argument1 = B;
pNew->Argument2 = C;
return pNew;
}
check( CreateObj( Function1, 08, 15 ) );
darf dann aber nicht vergessen in check die allokierte
Struktur wieder freizugeben.
Macht man keine dynamische Allokierung
struct CallFunc CreateObj( FuncPtr A, uint8_t B, uint8_t C )
{
struct CallFunc New;
New.theFunction = A;
New.Argument1 = B;
New.Argument2 = C;
return pNew;
}
dann wird wieder eine Menge über den Stack rumkopiert.
Hier fehlen dann in C die Möglichkeiten der Optimierungen die
C++ über Referenzen ermöglichen, das alles wieder zu streamlinen.
Du kannst auch Makros verwenden. Das ist aber u.U. nicht sehr eingängig.
Ungefähr so:
char check_impl( char fehler )
{
if ( fehler )
{
if ( soll_wiederholt_werden )
return 1;
else
mach_was_anderes();
}
return 0; /* Nicht wiederholen */
}
#define check( FCALL ) \
do { char f; do {f=FCALL;} while(check_impl(f)); } while(0)
Das funktioniert, ist aber nicht sehr hübsch....
Ist dann eben etwas Copy&Paste, schont aber den Stack, naja...
Ich denke aber, alles andere wäre für diesen Fall zu viel des Guten.
Vielen lieben Dank euch allen trotzdem für die tollen Antworten.
Ich werde das auf jeden Fall in "schlimmeren Fällen" (diese kommen
bestimmt) in Erwägung ziehen.
Beste Grüße,
Erik
> Ist dann eben etwas Copy&Paste,
Wenn diese Sequenz immer gleich ist, dann würde sich
in der Tat ein Makro dafür anbieten. Dann macht jemand
anderer den Copy&Paste