Ich habe einen Code, der variadische Parameter in va_list
umwandelt und dann die Liste an eine Funktion weiterleitet, die dann vsnprintf
aufruft. Dies funktioniert gut unter Windows und OS X, aber es schlägt mit seltsamen Ergebnissen unter Linux fehl.
Im folgenden Codebeispiel:
%Vor% Die Ausgabe des zweiten Aufrufs vsnprintf
ist 17 und das Ergebnis von strcmp
ist 31; aber ich verstehe nicht, warum vsnprintf
17 zurückgibt, da This is a test.
15 Zeichen ist, addiere NULL
und du erhältst 16.
Verwandte Themen, die ich gesehen habe, aber das Thema nicht behandeln:
Mit @ Mat's Antwort (ich verwende das va_list
-Objekt, was nicht erlaubt ist), kommt es direkt zum ersten verwandten Thread, mit dem ich verlinkt bin. Also habe ich stattdessen diesen Code versucht:
Welche, gemäß der C99 Spezifikation (Fußnote in Abschnitt 7.15 ), sollte funktionieren:
Es ist erlaubt, einen Zeiger auf eine va_list zu erstellen und diesen Zeiger zu übergeben zu einer anderen Funktion, in diesem Fall kann die ursprüngliche Funktion machen Weitere Verwendung der ursprünglichen Liste nach der anderen Funktion zurück.
Aber mein Compiler (gcc 4.4.5 im C99-Modus) gibt mir diesen Fehler bezüglich der ersten Zeile von myPrintfInner
:
Und die resultierende binäre erzeugt genau den gleichen Effekt wie beim ersten Mal.
Folgendes gefunden: Greift GCC einen Zeiger auf eine va_list, die an eine Funktion übergeben wurde, falsch?
Die vorgeschlagene Problemumgehung (die nicht garantiert funktionierte, aber in der Praxis funktionierte), ist die Verwendung von arg_copy
first:
Wie Sie wissen, besteht das Problem darin, dass Sie va_list
wiederverwenden. Wenn Sie Ihren Code nicht wie vorgeschlagen umstrukturieren möchten, können Sie das Makro C99 va_copy()
verwenden. so:
Auf Compilern, die C99 nicht unterstützen, können Sie stattdessen __va_copy()
oder verwenden Definieren Sie Ihre eigene va_copy()
-Implementierung (die nicht portierbar ist, aber Sie können Compiler- / Plattform-Sniffing immer in einer Header-Datei verwenden, wenn Sie dies wirklich brauchen). Aber wirklich, es ist 13 Jahre her - jeder ordentliche Compiler sollte C99 in diesen Tagen unterstützen, zumindest wenn man ihm die richtigen Optionen gibt ( -std=c99
für GCC).
Das Problem ist, dass Sie (abgesehen von der fehlenden return-Anweisung) den Parameter va_list
erneut verwenden, ohne ihn zurückzusetzen. Das ist nicht gut.
Versuchen Sie etwas wie:
%Vor%(Und schalten Sie die Warnungen Ihres Compilers ein.)
Ich glaube nicht, dass die Fußnote, auf die Sie verweisen, das bedeutet, was Sie denken. Ich lese es als: Wenn Sie ein va_list
direkt übergeben (als Wert, nicht als Zeiger), ist das einzige, was Sie im Aufrufer tun können, va_end
it. Aber wenn Sie es als Zeiger übergeben, könnten Sie zum Beispiel va_arg
im Aufrufer aufrufen, wenn der Aufgerufene nicht alle va_list
"verbraucht" hat.
Du könntest es aber mit va_copy
versuchen. Etwas wie:
Tags und Links c variadic-functions