Undefinierte Parameteranzahl / Funktionsgröße auf Stack bestimmen
-
FrEEzE2046 schrieb:
Die Frage ist doch einfach, WIE wird denn "von außen" argc an main gegeben. Wie kann ich mir das denn vorstellen?
ist nicht vergleichbar und der mechanismus ist afaik nicht definiert. das betriebsystem wird wohl den kommandozeilen-string in einzelne teilstrings parsen und mitzählen, wie viele freie leerzeichen da drin sind. das ist dann dein argc.
gib deiner funktion einfach einen parameter mit, wie viele argumente mitgeschickt wurden. die typen weißt du dann zwar immer noch nicht, aber die anzahl ist dann bekannt.
-
vadda schrieb:
gib deiner funktion einfach einen parameter mit, wie viele argumente mitgeschickt wurden. die typen weißt du dann zwar immer noch nicht, aber die anzahl ist dann bekannt.
Naja, der typ ist schon definiert. Sowohl bei undef. Parameterliste, als auch bei einem dyn. Array (wenn`s denn kein void* ist).
Das mit dem Mitzählen der leeren Stellen von main ist eine logische Erklärung. Bei der Geschichte mit den undef. Parametern bleibt aber die Frage, wie genau das ganze denn letztendlich ausschaut.
Kurz gefragt: Ist eine undef. Paramererliste im Sinne von int x,... im Prinzip (auf dem Stack) nichts anderes als ein array aus Integern?
Zudem ist die Frage wie gesagt, wie genau va_list denn an den Wert kommt. Was genau macht das Makro denn?
Ich will nicht kleinkariert sein und ich verstehe und weiß auch was ihr hier alle gesagt habt (übrigens danke für die vielen Reaktionen).
Es ist lediglich Wissensdurst, es interessiert mich einfach. Ich möchte wissen, wie sieht denn int x,... auf dem Stack aus (ist es ein Pointer?) und was macht va_list.Wenn mir da jemand helfen könnte, wäre mir sehr geholfen ... (intelligenter Satz).
Das Delphi/TurboPascal/ObjectPascal kein C/C++ ist, ist mir auch klar. Aber wenn Borland es auf die Reihe bekommt eine Funktion zu implementieren, die auch die Größe von dyn. Arrays ermittelt, wird dies jawohl auch in C/C++ und in Assembler sowieso möglich sein.
-
[quote="FrEEzE2046"]
vadda schrieb:
Naja, der typ ist schon definiert. Sowohl bei undef. Parameterliste, als auch bei einem dyn. Array (wenn`s denn kein void* ist).
Das mit dem Mitzählen der leeren Stellen von main ist eine logische Erklärung. Bei der Geschichte mit den undef. Parametern bleibt aber die Frage, wie genau das ganze denn letztendlich ausschaut.
Kurz gefragt: Ist eine undef. Paramererliste im Sinne von int x,... im Prinzip (auf dem Stack) nichts anderes als ein array aus Integern?
Nein, der Typ ist nicht definiert.
Eine Funktion, die so deklariert ist:void funk(int x, ...);
kennt nur den Typ des ersten Parameters. Die weiteren übergebenen Parameter können alle einen unterschiedlichen Typ haben.
-
Belli schrieb:
Nein, der Typ ist nicht definiert.
Eine Funktion, die so deklariert ist:void funk(int x, ...);
kennt nur den Typ des ersten Parameters. Die weiteren übergebenen Parameter können alle einen unterschiedlichen Typ haben.
Darum geht es mir zwar eigentlich nicht, aber dass was du da sagst ist mir absolut neu. Ich habe es an dieser Stelle auch gleich mal ausprobiert:
void funk(int x, ...) {}
bringt bei mir nach Aufruf
int main() { double d = 2.3; funk( 3, d, "Hallo" ); return 0; }
folgende Meldungen:
error C2664: 'TestSumme': Konvertierung des Parameters 3 von 'const char [6]' in 'int' nicht möglic 122
Warnung 1 warning C4244: 'Argument': Konvertierung von 'double' in 'int', möglicher Datenverlust 122Demnach muss wohl doch alles int sein, so wie ich sagte ...
-
FrEEzE2046 schrieb:
Aber wenn Borland es auf die Reihe bekommt eine Funktion zu implementieren, die auch die Größe von dyn. Arrays ermittelt, wird dies jawohl auch in C/C++ und in Assembler sowieso möglich sein.
geht ja auch, aber du musst es eben selbst programmieren. in C eingebaut ist sowas nicht (wie z.b. "hello".length() in Java o.ä.)
-
+fricky schrieb:
geht ja auch, aber du musst es eben selbst programmieren. in C eingebaut ist sowas nicht (wie z.b. "hello".length() in Java o.ä.)
Genau, daher ja der Thread. Hättest du vielleicht einen Ansatz?
Es geht mir ja gar nicht darum eine vorhandene Funktion / Makro zu benutzen, ich würde es auch selber programmieren, auch in assembler. Aber mir fehlt einfach der Ansatz ...
vlt. hab ich mich im bisherigen Thread-Verlauf undeutlich ausgedrücktIch mache da jetzt schon seit Tagen dran rum. Es fehlt aber einfach das Wissen, wie das Ganze zu realisieren ist.
-
FrEEzE2046 schrieb:
Demnach muss wohl doch alles int sein, so wie ich sagte ...
void funk(int x, ...) { } int main() { double d = 2.0; funk(1, d, "drei"); }
VS2008 schrieb:
1>va_test - 0 error(s), 0 warning(s)
hätte mich auch gewundert.
-
FrEEzE2046 schrieb:
Genau, daher ja der Thread. Hättest du vielleicht einen Ansatz?
naja, entweder du gibst der va_list eine ende-kennung als letzten wert mit (z.b. 0, -1, oder so), oder der erste ist die anzahl.
int summe (int x, ...) { va_list vl; int sum = 0; va_start (vl, x); while (x--) sum += va_arg (vl, int); return sum; } int main() { // beispiel: 4 werte, 1,2,3,-6 addieren printf ("%d\n", summe (4, 1,2,3,-6)); }
-
+fricky schrieb:
FrEEzE2046 schrieb:
Genau, daher ja der Thread. Hättest du vielleicht einen Ansatz?
naja, entweder du gibst der va_list eine ende-kennung als letzten wert mit (z.b. 0, -1, oder so), oder der erste ist die anzahl.
Mit anderen Worten:
Es geht NICHT!
UND: Die Parameter können alle unterschiedlichen Typs sein.@TE:
Würde es vielleicht etwas nützen, wenn es Dir hier jemand auf spanisch, italienisch, französisch oder so noch mal schreibt?
-
jupp! schrieb:
FrEEzE2046 schrieb:
Demnach muss wohl doch alles int sein, so wie ich sagte ...
void funk(int x, ...) { } int main() { double d = 2.0; funk(1, d, "drei"); }
VS2008 schrieb:
1>va_test - 0 error(s), 0 warning(s)
hätte mich auch gewundert.
ähm, natürlich. Irgendwie war ich jetzt beim dyn. array - einfach vergessen.
Belli schrieb:
@TE:
Würde es vielleicht etwas nützen, wenn es Dir hier jemand auf spanisch, italienisch, französisch oder so noch mal schreibt?Das wäre wirklich super! ...
Bleib doch mal locker. Ich verstehe schon was du meinst, aber wenn es NICHT GEHT, dann ist also va_start und va_list ein Makro, was gar nicht funktioniert oder wie? Irgendwie machen die es ja wohl auch und wie bereits erwähnt schaffen das auch andere Sprachen ... schwer vorzustellen bei einer Sache die angeblich gar nicht funktioniert.
Verstehst du jetzt was ich meine?
-
FrEEzE2046 schrieb:
Ich verstehe schon was du meinst, aber wenn es NICHT GEHT, dann ist also va_start und va_list ein Makro, was gar nicht funktioniert oder wie?
nein, du hast es immer noch nicht verstanden. die va_*-makros werden entweder mit hardgecodeten typen verwendet, oder es wird ein formatstring benutzt (z.b. bei printf), in dem die anzahl und die typen der parameter kodiert sind. die information kommt also nicht von irgendwo her, sondern wird vom programmierer vorgegeben. und das musst du genauso machen, wenn dir kein besserer mechanismus einfällt.
-
FrEEzE2046 schrieb:
Ich verstehe schon was du meinst, aber wenn es NICHT GEHT, dann ist also va_start und va_list ein Makro, was gar nicht funktioniert oder wie? Irgendwie machen die es ja wohl auch und wie bereits erwähnt schaffen das auch andere Sprachen ... schwer vorzustellen bei einer Sache die angeblich gar nicht funktioniert.
Verstehst du jetzt was ich meine?
DU willst die Information zur Laufzeit haben. Die MAKROS liefern die erforderlichen Informationen zur Compilezeit.
Wenn es in zB Delphi funktioniert, daß man mit Hi und Lo (oder ähnlich) jederzeit die Größe oder Grenzen eines Arrays abfragen kann, dann heißt das, daß diese Informationen im Array gespeichert sind - wie oder wo auch immer.
Das ist in C aber nicht so ...
-
Nachtrag:
Lies Dich doch mal in die Funktionsweise dieser Makros ein, eventuell bringt das etwas Licht ins Dunkel.
Mit diesen Makros holst Du innerhalb der Funktion einen Parameter vom Stack. Da Du dabei den Typ des Parameters angeben mußt, 'weiß' das Makro, wie groß der Parameter ist, und kann einen Zeiger genau so weit weiterbewegen, daß er auf den nächsten Parameter zeigt (mal so ganz grob gesprochen, ich hoffe, es ist einigermaßen verständlich).
Die Makros stellen Dir nur einen einfachen Weg zur Verwaltung eines Zeigers in die Parameterliste zur Verfügung, sonst nix.
-
jupp! schrieb:
nein, du hast es immer noch nicht verstanden. die va_*-makros werden entweder mit hardgecodeten typen verwendet, oder es wird ein formatstring benutzt (z.b. bei printf), in dem die anzahl und die typen der parameter kodiert sind. die information kommt also nicht von irgendwo her, sondern wird vom programmierer vorgegeben. und das musst du genauso machen, wenn dir kein besserer mechanismus einfällt.
Also, ich verstehe es so:
Du meinst, dass man printf auch bescheißen kann. Ungefähr so:printf( "Test %d %d t %d tata %d %d %d %d %d %d %d", 5, 6, 7 );
Da es lediglich noch "%" sucht und den Wert dann anhand der undef. Parameter ersetzt. Wenn es mehr sind als Parameter angegebenen, läuft er den Stack einfach weiter ab ohne es zu merken.
Jetzt hab ich zwei Möglichkeiten:
a) template schreiben was auch in dyn. arrays längen Informationen festhält.
b) 0 Argument an Parameterliste anfügen und darauf prüfen ...
-
FrEEzE2046 schrieb:
Wenn es mehr sind als Parameter angegebenen, läuft er den Stack einfach weiter ab ohne es zu merken.
im prinzip richtig. was genau passiert, ist afaik nicht festgelegt. es ist einfach undefiniert.
a) template schreiben was auch in dyn. arrays längen Informationen festhält.
du bist hier übrigens im c-forum, c++ ist nebenan. wenn du in c++ programmierst, kann std::vector als dynamisches array verwendet werden.
b) 0 Argument an Parameterliste anfügen und darauf prüfen ...
geht aber nur wenn du die typen in der liste alle kennst und keine 0 als argument übergeben werden kann/darf.
-
jupp! schrieb:
a) template schreiben was auch in dyn. arrays längen Informationen festhält.
du bist hier übrigens im c-forum, c++ ist nebenan. wenn du in c++ programmierst, kann std::vector als dynamisches array verwendet werden.
Ja, ist mir schon klar^^. Auch einen vector könnte ich nehmen, richtig. Nun gut, ich denke ich weiß jetzt wie ich verfahren werde.
-
FrEEzE2046 schrieb:
Also, ich verstehe es so:
Du meinst, dass man printf auch bescheißen kann. Ungefähr so:printf( "Test %d %d t %d tata %d %d %d %d %d %d %d", 5, 6, 7 );
genau, wenn du es aber tust, ist das Verhalten undefiniert. Das bedeutet, dass alles mögliche passieren kann: du kannst Müll bekommen, du kannst was vernünftiges bekommen, dein programm kann mit segfault sich verabschieden, dein Computer explodiert, der dritte Weltkrieg wird ausgelöst ...
btw: was andere Sprachen kennen und können, ist irrelevant. Wenn C sowas nicht kennt, dann kennt es eben nicht, auch wenn du dich auf den Kopf stellst und laut schreist "aber in Delphi geht es".
-
Irgendwie komme ich mir vor, wie in einer Zeitblase ... heute Vormittag die Frage, sollte man meinen zwei, drei Posts und alles ist gesagt ... Nee, ich komme nach Stunden zurück und es sind drei Seiten immer desselben Inhalts geworden.
Timeloop of Nonsense ... viel Spaß noch!