[C] variable anzahl an Argumenten an einen Funktionspointer

Gast #1953275
Lesenswert?

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
#1953290
Lesenswert?

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?
Gast #1953294
Lesenswert?

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.
Gast #1953330
Lesenswert?

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?
Gast #1953365
Lesenswert?

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.
Gast #1953411
Lesenswert?

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.
Gast #1953424
Lesenswert?

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 :-)
Gast #1953980
Lesenswert?

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!
#1954147
Lesenswert?

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.
#1954176
Lesenswert?

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?
Gast #1954181
Lesenswert?

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. :-)
Gast #1954219
Lesenswert?

@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
Gast #1954232
Lesenswert?

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ß.
#1954252
Lesenswert?

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...
#1954255
Lesenswert?

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.
#1954265
Lesenswert?

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?
#1954273
Lesenswert?

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.
Gast #1954875
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren