Hallo, ich suche in C die Möglichkeit einem Funktionspointer eine variable Anzahl von Argumenten zu übergeben - scheitere aber daran, was mich letzte Nacht den Schlaf geraubt hat!!! Idealerweise haben hierbei die Argumente auch verschiedene Variablentypen :-/ Kann mir jemand einen Tip oder ein Beispiel hierfür geben, damit ich die nächste Nacht nicht vor Problemen, sondern vor Realisierungen sitze? Vielen Dank
Meinst Du sowas wie bei printf? Dann such mal nach va_list und änliches. Beispiel weiter unten auf http://www.cplusplus.com/reference/clibrary/cstdarg/va_start/ MfG Mark
Markus, der Kaffee-Säufer schrieb: > Hallo, > > ich suche in C die Möglichkeit einem Funktionspointer eine variable > Anzahl von Argumenten zu übergeben - scheitere aber daran, was mich > letzte Nacht den Schlaf geraubt hat!!! > > Idealerweise haben hierbei die Argumente auch verschiedene > Variablentypen :-/ kriegst du es denn ohne Funktionspointer hin? Also eine Funktion zu machen, die variadisch ihre Argumente übernimmt?
Mal ein vereinfachter Ansatz zum Nachdenken: Es ist total egal, was, wie viel und warum du an eine Funktion übergibst. Das geht in C so gut, weil der Aufrufer dafür verantwortlich ist: - erst alle Argumente auf den Stack zu legen, - die Funktion aufzurufen und anschließend - alle Argumente wieder vom Stack zu nehmen. Die Prototypen haben sozusagen formellen Charakter. Deshalb funktionieren z.B. auch Funktionen mit leerer Parameterliste noch (alter K&R-Stil) -- eben weil es egal ist, was und wie viel mitkommt. Schlimmstenfalls liest die aufgerufene Funktion eben zu viel und läuft in einen Zugriffsfehler oder solcherlei.
Sven P. schrieb: > Es ist total egal, was, wie viel und warum du an eine Funktion > übergibst. Das geht in C so gut, weil der Aufrufer dafür verantwortlich > ist: > - erst alle Argumente auf den Stack zu legen, > - die Funktion aufzurufen und anschließend > - alle Argumente wieder vom Stack zu nehmen. Das mag bei vielen Compilern faktisch so sein, aber "in C" wird über die Art, wie Argumente übergeben werden, kein Wort verloren. > Die Prototypen haben sozusagen formellen Charakter. > > Deshalb funktionieren z.B. auch Funktionen mit leerer Parameterliste > noch (alter K&R-Stil) -- eben weil es egal ist, was und wie viel > mitkommt. Nein. Aufrufer und aufgerufene Funktion müssen sich einig darüber sein, was übergeben wird. Wenn die Paramterliste beim Aufruf nicht explizit bekannt ist, generiert der Compiler eben eine implizite Liste, die er aus den übergebenen Argumenten ermittelt. Er vertraut dann einfach darauf, daß die stimmt, weil er keine Möglichkeit hat, es zu überprüfen. Das hat aber nichts damit zu tun, wer für was zuständig ist oder wie die Argumente dann übergeben werden. > Schlimmstenfalls liest die aufgerufene Funktion eben zu viel und läuft in > einen Zugriffsfehler oder solcherlei. Würde dir denn was schlimmeres einfallen, das noch passieren könnte?
Rolf Magnus schrieb: > Das mag bei vielen Compilern faktisch so sein, aber "in C" wird über die > Art, wie Argumente übergeben werden, kein Wort verloren. Das ist richtig. Gerade deshalb ist die von mir beschriebene Aufrufkonvention ja auch als 'cdecl' bekannt... Hätte ich aber eindeutiger formulieren sollen, wohl wahr. > Nein. Aufrufer und aufgerufene Funktion müssen sich einig darüber sein, > was übergeben wird. Wenn die Paramterliste beim Aufruf nicht explizit > bekannt ist, generiert der Compiler eben eine implizite Liste, die er > aus den übergebenen Argumenten ermittelt. Er vertraut dann einfach > darauf, daß die stimmt, weil er keine Möglichkeit hat, es zu überprüfen. Ja. Und wo sind sich Aufrufer und Aufgerufener nun einig? Ich würde sagen, einzig in der Aufrufkonvention. > Das hat aber nichts damit zu tun, wer für was zuständig ist oder wie die > Argumente dann übergeben werden. Sondern? >> Schlimmstenfalls liest die aufgerufene Funktion eben zu viel und läuft in >> einen Zugriffsfehler oder solcherlei. > > Würde dir denn was schlimmeres einfallen, das noch passieren könnte? Nein, was Schlimmeres, als auf verbotenen Speicher zuzugreifen fällt mir nicht ein. Es sei dir aber gerne überlassen, dir sämtliche Nebenwirkungen auszumalen, die so ein Zugriff etwa in Siemens-SPS haben könnte.
Sven P. schrieb: >> Nein. Aufrufer und aufgerufene Funktion müssen sich einig darüber sein, >> was übergeben wird. Wenn die Paramterliste beim Aufruf nicht explizit >> bekannt ist, generiert der Compiler eben eine implizite Liste, die er >> aus den übergebenen Argumenten ermittelt. Er vertraut dann einfach >> darauf, daß die stimmt, weil er keine Möglichkeit hat, es zu überprüfen. > > Ja. Und wo sind sich Aufrufer und Aufgerufener nun einig? Ich würde > sagen, einzig in der Aufrufkonvention. Natürlich, aber die muß nicht so aussehen, wie du sie beschrieben hast. Sie ist im Prinzip beliebig, solange sie nur auf beiden Seiten gleich ist. Du hast oben drei Regeln erwähnt und behauptet, daß es nur aufgrund dieser möglich sei, Funktionsdeklarationen ohne explizite Parameterliste zu haben. Diese Regeln sind aber keine C-Regeln, und die Deklarationen würden auch ohne sie funktionieren. Deshalb hat Existenz dieser Art der Deklaration nichts damit zu tun, wer den Stack aufräumt. >> Das hat aber nichts damit zu tun, wer für was zuständig ist oder wie die >> Argumente dann übergeben werden. > Sondern? Wie ich schon schrieb, damit, ob der Compiler prüfen kann, ob der Aufruf korrekt ist. >>> Schlimmstenfalls liest die aufgerufene Funktion eben zu viel und läuft >>> in einen Zugriffsfehler oder solcherlei. >> >> Würde dir denn was schlimmeres einfallen, das noch passieren könnte? > Nein, was Schlimmeres, als auf verbotenen Speicher zuzugreifen fällt mir > nicht ein. Vielleicht hab ich's ja falsch verstanden, aber deine Aussage klang, als sei das ja nicht weiter tragisch.
Ach so siehst du das.
Ich schrieb doch:
> Mal ein vereinfachter Ansatz zum Nachdenken:
Die Ausführungen sind vereinfacht, hamwa ja jetzt festgestellt. Wenn man
sie aber durchgeht, kommt man jedenfalls zum Ergebnis:
Eine variable Anzahl von Argumenten funktioniert beim Funktionszeiger
genauso, wie bei fest verdrahteten Funktionen.
Mehr wollte ich eigentlich nicht sagen, nur sollte es etwas anschaulich
werden. Mag sein, dass andere Compiler andere Konventionen verwenden,
alle führen aber auf diese Erkenntnis :-)
Hallo, da bin ich wieder! Ich habe bei mir den Fall, das ich 0 bis 3 Argumente übergeben will/muss. Ich denke ich schreibe mir einen kleinen Parser, der überprüft, wie viele Argumente anstehen und schreibe halt entsprechende Routinen die diese dann via Switch-Anweisung aufrufen. -Ich denke das wird der einfachste Weg sein. Auch werde ich mal versuchen, eine Art Lookup zu schreiben. Hab ja noch Wochenende - da kann ich ja noch einiges ausprobieren ;-) Aber vielen Dank soweit!
Markus, der Kaffee-Säufer schrieb: > Hallo, da bin ich wieder! > > Ich habe bei mir den Fall, das ich 0 bis 3 Argumente übergeben > will/muss. 0 geht sowieso nicht. Jede variadische Funktion muss mindestens 1 Argument haben, welches dazu dient die Datentypen der restlichen (für die aufgerufene Funktion) unbekannten Argumente zu identifizieren. Überleg einfach mal, warum man bei einem printf alles weglassen kann, bis auf den Formatstring und warum wohl der Protoyp für printf so
1 | int printf( const char*, ... ); |
aussieht und der Formatstring nicht optional ist. > Ich denke ich schreibe mir einen kleinen Parser, der überprüft, wie > viele Argumente anstehen und schreibe halt entsprechende Routinen die > diese dann via Switch-Anweisung aufrufen. -Ich denke das wird der > einfachste Weg sein. Schau dir einfach an, wie die Argumente an main() übergeben werden. Man muss nicht für alles das Rad neu erfinden, manchmal reicht es auch, wenn man sich ansieht, wie das andere Sprachelemente machen.
Das ist unfug. Bevor schreiben, austesten: void blah(...) { } blah(1, 4, "Hallo"); blah(); Wessen compiler meckert da? Meiner nicht.
und wie kommst du jetzt an die Parameter ran?
Hat er bestimmt schon ausgetestet :-)
DerAlbi schrieb: > Das ist unfug. Bevor schreiben, austesten: > > > void blah(...) > { > > } > > > blah(1, 4, "Hallo"); > blah(); > > > Wessen compiler meckert da? > Meiner nicht. Meiner übrigens schon:
1 | klaus@i4a:~ > cat t.c |
2 | void t(...) |
3 | { |
4 | } |
5 | klaus@i4a:~ > gcc -Wall t.c |
6 | t.c:1: error: ISO C requires a named argument before ‘...’ |
Vielleicht solltest du mal deinen K&R-Compiler updaten :-) PS: Hattest du das eigentlich getestet?
an die parameter kommt man ganz normal über die argumentliste... aber interessant das mache compiler wirklich meckern. Ist mir noch nicht passiert, sry. Ich finde den Parameter persönlich aber auch unnötig am anfang. Eine VariableArgumentList basiert auf der Übergabe eines Pointers auf eine Pointerliste und zusätzlich noch natürlich die Listengröße. Die Typen in der Argumentliste sind nicht fest definiert. Auch nicht durch den ersten parameter (man übergibt bei printf char* und hinten kommen int, double und sonstiger unfug) ISO C. Naja. :-)
DerAlbi schrieb: > an die parameter kommt man ganz normal über die argumentliste... Reden wir beide von C? Wie soll das gehen? Z.B. so:
1 | void t(...) |
2 | {
|
3 | printf( ... ); // alles ausgeben |
4 | }
|
Man lernt ja nie aus ...
DerAlbi schrieb: > aber interessant das mache compiler wirklich meckern. Ist mir noch nicht > passiert, sry. JEDER ISO-C-Compiler muß das meckern.
DerAlbi schrieb: > an die parameter kommt man ganz normal über die argumentliste... für va_start braucht man aber den ersten parameter mit namen.
@Klaus Wachtler void t(...) { printf( ... ); // alles ausgeben } wie kommt man darauf, das printf(...) so funktioniert?? Geschweigedenn der zugriff und weitergabe von varArgs? Sehr fundiert. Also wer Beispiele bringt die syntaktisch gar niht funktionieren können, soll sich nicht beschweren, dass es nicht funktionert :-/ Ich geb zu, mein compiler ist wohl nicht ISO konform.. aber welcher ist das schon heutzutage noch ;-) Jeder hat doch seine eigenen erweiterungen.. aber is schon ok :-) Ordentlicher code muss einen dummyparameter haben - verstanden
DerAlbi schrieb: > an die parameter kommt man ganz normal über die argumentliste... Und was übergibst du als zweites Argument an va_start? DerAlbi schrieb: > Ist mir noch nicht passiert, sry. Vermutlich arbeitest du noch im historischen pre-ANSI-C-Modus aus den Achtzigern des letzten Jahrhunderts.
Ach, noch wasS: DerAlbi schrieb: > Ordentlicher code muss einen dummyparameter haben - verstanden Woran erkennt die aufgerufene Funktion denn ohne den "Dummyparameter" eigentlich, daß gar keine Argumente kommen? Ähnlich wie bei Arrays braucht man doch auch bei der variablen Parameterliste immer entweder einen zusätzlichen Wert, der die Anzahl angibt oder irgendeinen Ende-Marker, und beides bedeutet zwangsläufig, daß man auf jeden Fall mindestens ein Argument übergeben muß.
DerAlbi schrieb: > @Klaus Wachtler > > void t(...) > { > printf( ... ); // alles ausgeben > } > > wie kommt man darauf, das printf(...) so funktioniert?? Ich habe nicht behauptet, daß es so ginge. Im Gegenteil, ich bin sicher daß es gar nicht geht ohne zumindest einen benannten Parameter, weder so noch anders. Wenn du Teile von mir zitierst, dann bitte nicht sinnentstellend. Das war vielmehr die Frage an dich, wie du das lösen willst: DerAlbi schrieb: > an die parameter kommt man ganz normal über die argumentliste...
DerAlbi schrieb: > Das ist unfug. Bevor schreiben, austesten: > > > void blah(...) > { > > } > > > blah(1, 4, "Hallo"); > blah(); > > > Wessen compiler meckert da? > Meiner nicht. Aha. Dann führ doch bitte mal die Internals von blah aus. Ich hätte von dir gerne den Code in blah gesehen, so dass ich diese Aufrufe machen kann blah( "arg1" ); blah( 1 ) blah( 1, "arg1" ); blah( "arg1", "arg2" ); blah( 3.1415 ); blah( 3.1415f ); // der ist gemein. Vorsicht Falle blah(); Für den Anfang genügt es vollkommen, wenn die Funktion die Funktionsargumente einfach ausgibt. printf ist dafür fein. Also: Wie sieht blah aus? Nur weil ein bestimmter Compiler etwas nicht anmeckert, heisst das noch lange nicht, das es richtig ist.
DerAlbi schrieb: > Ich finde den Parameter persönlich aber auch unnötig am anfang. > Eine VariableArgumentList basiert auf der Übergabe eines Pointers auf > eine Pointerliste und zusätzlich noch natürlich die Listengröße. Die > Typen in der Argumentliste sind nicht fest definiert. Auch nicht durch > den ersten parameter (man übergibt bei printf char* und hinten kommen > int, double und sonstiger unfug) Du redest jetzt aber nicht von C, oder? Vielleicht kannst du ja im C-Standard auch noch die Stelle benennen an der von einer VariableArgumentList die Rede ist, die so realisiert sein muss, wie du das beschreibst. > Die > Typen in der Argumentliste sind nicht fest definiert. Woher weiß dann die Funktion, welche Datentypen im Spiel sind?
DerAlbi schrieb: > Ordentlicher code muss einen > dummyparameter haben - verstanden Ich glaub du misverstehst da etwas ganz gewaltig. Es ist genau dieser, wie du es ausdrückst, Dummyparameter, der erst variadische Funktionen möglich macht. Das was du als Dummyparameter bezeichnest, ist der Schlüssel zu variadischen Funktionen. Und er ist alles andere als einfach nur 'dummy'. > Das ist unfug. Bevor schreiben, austesten: Das kann ich zurückgeben. Hast du schon mal eine variadische Funktion geschrieben? Wenn nein, dann empfehle ich dir mal eine zu implementieren. Dann wird dir nämlich vieles klarer. Unter anderem zb auch die automatischen Promotionregeln, die hier plötzlich zu greifen anfangen.
Habt recht, bin dumm. Hab schon Funktionen mit Varrgs geschrieben, hatte aber auch bisher immer (zufällig) feste Parameter. Dann hab ich das gelesen und ein kleines Testprogramm compilieren lassen und gesehen dass mein compiler nicht meckert. Deswegen fehlschuss. Sry. Auch wenns bei mir compiliert - was wohl die ausmahme ist - isses in der Tat kompliziert dann auf die Args zuzugreifen. Blöder Albi. :-) Aber nu schlauer.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.