Angenommen, ich habe eine C-Funktion, die eine variable Anzahl von Argumenten akzeptiert: Wie kann ich eine andere Funktion aufrufen, die eine variable Anzahl von Argumenten von innen erwartet, und alle Argumente übergeben, die in die erste Funktion gelangt sind?
Beispiel:
void format_string(char *fmt, ...);
void debug_print(int dbg_lvl, char *fmt, ...) {
format_string(fmt, /* how do I pass all the arguments from '...'? */);
fprintf(stdout, fmt);
}
Ihr Beispiel sieht für mich etwas seltsam aus, da Sie fmt sowohl an format_string() als auch an fprintf() übergeben. Sollte format_string() irgendwie einen neuen String zurückgeben?
– Christoph Johnson
15. Oktober 2008 um 17:14 Uhr
Beispiel macht keinen Sinn. Es war nur, um den Umriss des Codes zu zeigen.
– Vicent Martí
15. Oktober 2008 um 17:22 Uhr
“sollte gegoogelt werden”: Ich stimme nicht zu. Google hat viel Lärm (unklare, oft verwirrende Informationen). Eine gute (abgestimmte, akzeptierte Antwort) auf Stackoverflow zu haben, hilft wirklich!
– Ansgar
6. Februar 2009 um 9:53 Uhr
Nur zum Abwägen: Ich bin von Google auf diese Frage gekommen, und da es sich um einen Stapelüberlauf handelte, war ich sehr zuversichtlich, dass die Antwort nützlich sein würde. Also frag weg!
– Tenpn
24. Februar 2009 um 12:18 Uhr
@Ilya: Wenn niemand etwas außerhalb von Google aufgeschrieben hätte, gäbe es keine Informationen, nach denen man bei Google suchen könnte.
– Erik Kaplun
29. August 2012 um 20:27 Uhr
SmacL
Um die Ellipsen weiterzugeben, initialisieren Sie a va_list wie gewohnt und übergeben Sie es einfach an Ihre zweite Funktion. Sie verwenden nicht va_arg(). Speziell;
Der Code stammt aus der Frage und ist eigentlich nur eine Veranschaulichung, wie Ellipsen konvertiert werden, und nicht irgendetwas Funktionelles. Wenn man es sich ansieht format_string wird auch kaum nützlich sein, da es in situ Änderungen an fmt vornehmen müsste, was sicherlich auch nicht getan werden sollte. Zu den Optionen würde gehören, format_string ganz loszuwerden und vfprintf zu verwenden, aber das macht Annahmen darüber, was format_string tatsächlich tut, oder format_string soll einen anderen String zurückgeben. Ich werde die Antwort bearbeiten, um letzteres zu zeigen.
– SmacL
24. Februar 2012 um 16:35 Uhr
Wenn Ihre Formatzeichenfolge dieselben Formatzeichenfolgenbefehle wie printf verwendet, können Sie auch einige Compiler wie gcc und clang dazu bringen, Ihnen Warnungen auszugeben, wenn Ihre Formatzeichenfolge nicht mit den tatsächlich übergebenen Argumenten kompatibel ist. Siehe das GCC-Funktionsattribut ‘ Format’ für weitere Details: gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html.
– Doug Richardson
16. November 2013 um 19:00 Uhr
Dies scheint nicht zu funktionieren, wenn Sie die Argumente zweimal hintereinander übergeben.
– Fotanus
10. Juni 2015 um 4:20 Uhr
@fotanus: wenn du eine funktion aufrufst mit der argptr und die aufgerufene Funktion verwendet die argptr Überhaupt ist das einzig Sichere, anzurufen va_end() und dann neu starten va_start(argptr, fmt); neu zu initialisieren. Oder Sie können verwenden va_copy() wenn Ihr System es unterstützt (C99 und C11 erfordern es; C89/90 nicht).
– Jonathan Leffler
15. Juni 2015 um 1:32 Uhr
Bitte beachten Sie, dass der Kommentar von @ThomasPadron-McCarthy jetzt veraltet ist und der endgültige fprintf in Ordnung ist.
– Friedrich
13. September 2016 um 20:19 Uhr
Es gibt keine Möglichkeit, (z. B.) printf aufzurufen, ohne zu wissen, wie viele Argumente Sie ihm übergeben, es sei denn, Sie möchten in ungezogene und nicht tragbare Tricks geraten.
Die allgemein verwendete Lösung besteht darin, immer eine alternative Form von vararg-Funktionen bereitzustellen, also printf hat vprintf was dauert va_list anstelle der .... Das ... Versionen sind nur Wrapper um die va_list Versionen.
Beachten Sie, dass vsyslog ist nichtPosix konform.
void func(type* values) {
while(*values) {
x = *values++;
/* do whatever with x */
}
}
func((type[]){val1,val2,val3,val4,0});
Noch besser ist dieser Trick: #define callVardicMethodSafely(values...) ({ values *v = { values }; _actualFunction(values, sizeof(v) / sizeof(*v)); })
– Richard J.Ross III
3. März 2012 um 22:54 Uhr
@RichardJ.RossIII Ich wünschte, Sie würden Ihren Kommentar erweitern, er ist so kaum lesbar, ich kann die Idee hinter dem Code nicht erkennen und er sieht tatsächlich sehr interessant und nützlich aus.
– Penelope
30. März 2012 um 10:09 Uhr
@ArtOfWarfare Ich bin mir nicht sicher, ob ich zustimme, dass es ein schlechter Hack ist, Rose hat eine großartige Lösung, aber es beinhaltet die Eingabe von func( (type[]){Wert1, Wert2, 0}); was sich klobig anfühlt, während wenn Sie #define func_short_cut(…) func((type[]){VA_ARGS}); dann könnten Sie einfach func_short_cut(1, 2, 3, 4, 0) aufrufen; was Ihnen die gleiche Syntax wie eine normale variadische Funktion mit dem zusätzlichen Vorteil von Roses nettem Trick gibt … was ist hier das Problem?
– Chrispepper1989
24. Juli 2013 um 14:05 Uhr
Was ist, wenn Sie 0 als Argument übergeben möchten?
– Julian Gold
10. September 2014 um 8:50 Uhr
Dazu müssen Ihre Benutzer daran denken, mit einer abschließenden 0 anzurufen. Wie ist es sicherer?
– vgl. engr
26. Februar 2016 um 21:26 Uhr
Benutzer2023370
In großartigem C ++ 11 können Sie verschiedene Vorlagen verwenden:
Sie können zwar das Übergeben des Formatierers lösen, indem Sie ihn zuerst im lokalen Puffer speichern, aber das erfordert Stack und kann manchmal ein Problem darstellen. Ich habe folgendes versucht und es scheint gut zu funktionieren.
Ihr Beispiel sieht für mich etwas seltsam aus, da Sie fmt sowohl an format_string() als auch an fprintf() übergeben. Sollte format_string() irgendwie einen neuen String zurückgeben?
– Christoph Johnson
15. Oktober 2008 um 17:14 Uhr
Beispiel macht keinen Sinn. Es war nur, um den Umriss des Codes zu zeigen.
– Vicent Martí
15. Oktober 2008 um 17:22 Uhr
“sollte gegoogelt werden”: Ich stimme nicht zu. Google hat viel Lärm (unklare, oft verwirrende Informationen). Eine gute (abgestimmte, akzeptierte Antwort) auf Stackoverflow zu haben, hilft wirklich!
– Ansgar
6. Februar 2009 um 9:53 Uhr
Nur zum Abwägen: Ich bin von Google auf diese Frage gekommen, und da es sich um einen Stapelüberlauf handelte, war ich sehr zuversichtlich, dass die Antwort nützlich sein würde. Also frag weg!
– Tenpn
24. Februar 2009 um 12:18 Uhr
@Ilya: Wenn niemand etwas außerhalb von Google aufgeschrieben hätte, gäbe es keine Informationen, nach denen man bei Google suchen könnte.
– Erik Kaplun
29. August 2012 um 20:27 Uhr