einen float-Wert auslesen, der einer Funktion mit variabler Parameterliste übergeben wurde
-
hi,
ich habe folgende Funktion:void tmpfunc(...) { va_list arg; int Anzahl = 1; va_start(arg,Anzahl); float f = va_arg(arg,float); }diese Funktion rufe ich nun auf die folgende Art auf:
float f = 5.0; tmpfunc(f);Das Problem ist jetzt nur, dass das f in der Funktion nicht den Wert von 5 hat, sondern irgendwas stark negatives....
Mir ist folgendes aufgefallen: Übernimmt eine Funktion direkt eine float so wird der Wert deim Callen direkt mit "push val" übergeben, ruft man dagegen eine Funktion mit variabler Parameterliste, so rechnet er die Zahl erst um und übergibt sie dann:
fld dword ptr [f] sub esp,8 fstp qword ptr [esp]Kennt da jemand einen Ausweg aus der Misere (außer, dass man double als Typ verwendet) ?
danke im voraus
-
ERstens braucht eine var-arg Funktion mindestens einen festen Parameter, der als Orientierungspunkt für va_start() verwendet werden kann. Und zweitens führt C++ auf den variablen Argumenten noch "numeric promotion" durch - alle float-Werte werden nach double konvertiert, char und short nach int (das bedeutet, daß es wenig Sinn macht, float, char oder short aus der Argumentliste ziehen zu wollen).
PS: Wozu brauchst du überhaupt die variable Argumentliste, wenn du doch nur einen Wert erwartest?
-
Ich schreibe an einer Klasse, die einen Funktionszeiger repräsentieren soll. Dabei soll es egal sein, ob er auf eine normale Funktion oder auf eine Memberfunktion zeigt.
Ich habe jetzt schon entsprechende Funktionen (in asm) geschrieben, die Adressen von Funktionen auslesen, bzw. sie analysieren.
Zur Zeit arbeite ich eben an der Anbindung des ASM-Codes an C++. Am liebsten währe mir da eine Funktion call() gewesen die irgendwelche Params übernimmt (deshalb das ...) und diese 1zu1 der funktion übergibt, die aufgerufen wird. Wenn diese Funktion aber float erwartet schlägt das alles fehl, da sie double geliefert bekommt.
Ich werde das alles jetzt so lösen, dass man vorher angeben muss, welche Parameter die Funktion erwartet und dann passe ich das eben entsprechend an. Das ist zwar sicherer, aber eben auch langsamer.
PS: man muss nicht unbedingt, die Anzahl der Parameter übergeben, da man das auch über ASM auslesen kann (ob man da mal nen kurzen Artikel zu schreiben könnte?! wäre nämlich kein Problem ;))
-
ESS_CB schrieb:
PS: man muss nicht unbedingt, die Anzahl der Parameter übergeben, da man das auch über ASM auslesen kann (ob man da mal nen kurzen Artikel zu schreiben könnte?! wäre nämlich kein Problem ;))
Durchaus möglich, daß du auf ASM-Ebene da etwas drehen kannst (aber wie das aussehen könnte, hängt von deinem System ab), auf C(++)-Ebene mußt du wissen, was für Parameter (Anzahl und Typ) du übergeben bekommen hast.
PS: Wegen dem Artikel kannst du ja bei redaktion@c-plusplus.net anfragen, ob Interesse besteht.
-
ESS_CB schrieb:
Ich schreibe an einer Klasse, die einen Funktionszeiger repräsentieren soll. Dabei soll es egal sein, ob er auf eine normale Funktion oder auf eine Memberfunktion zeigt.
Wenn es nicht noch um weitere Spezialproblematiken geht: solche Umsetzungen gibt es ohne über ASM zu gehen (Thema: Funktoren). Siehe auch Modernes C++ Design von Alexander Andrescu...
cu André
-
ehm, ich hab mir mal ganz kurz (!!) die Funktoren von Boost angeschaut und ich habe keine Möglichkeit gefunden, so ein Teil an eine Funktion eines bestimmten Objekts zu binden.
Ich bräuchte nämlich einen Pointer, der direkt auf eine Funktion eines bestimmten Objekts zeigt und _NICHT_ auf einfach nur auf eine bestimmte Funktion der Klasse.
-
Da hast du wahrscheinlich nicht lange/genau genug hingeschaut
Sowas gibt es schon in der Standard-Bibliothek ( bind1st(mem_fun(&Typ::methode),objekt);) - die Boost-Variante sieht vermutlich ein Stück eleganter aus.
-
CStoll schrieb:
die Boost-Variante sieht vermutlich ein Stück eleganter aus.
Vermutlich? Hast Du selbst sie noch nie benutzt?
Wäre dann:
bind( &Typ::methode, objekt, _1 );Der Vorteil ist, anders als die Standard-Binder funktioniert das auch mit Methoden mit mehr (oder weniger) als einem Parameter:
bind( &Typ::methode, objekt, _1, _2, _3 );Mischen geht natürlich auch:
bind( &Typ::methode, _1, param1, _2, _3, param4 );
-
LordJaxom schrieb:
CStoll schrieb:
die Boost-Variante sieht vermutlich ein Stück eleganter aus.
Vermutlich? Hast Du selbst sie noch nie benutzt?
Ja, leider. Ich kenne zwar Boost, aber ich komme nicht oft dazu, es selber einzusetzen.
-
verdammt schick, das ding, muss man mal sagen

ok, danke, ich glaub die Arbeit kann ich mir jetzt sparen
