Beste Weg, um eine va_list, die für die Spätere Verwendung in C/C++
Ich bin mit einer va_list zu konstruieren, ein string, der dargestellt wird.
void Text2D::SetText(const char *szText, ...)
Dies ist alles schön und gut, aber jetzt hat der Anwender die Möglichkeit die Sprache zu ändern, während die Anwendung ausgeführt wird. Ich brauche, um zu regenerieren, die alle text-strings und re-cache der text-bitmaps nach der Initialisierung. Ich möchte zum speichern der va_list und verwenden Sie es, Wann immer der text erzeugt werden soll.
Ihnen etwas mehr hintergrund, dies geschehen muss, in dem Fall, wo der Schlüssel-string, dass ich die übersetzung hat ein dynamisches Stück von Daten.
"Player Score:%d"
Ist der Schlüssel-string, die ich brauche, um zu übersetzen. Ich möchte die Anzahl(N) in der va_list für die spätere Verwendung (außerhalb der Funktion initialisiert den text) in dem Fall, dass es muss neu übersetzt nach der Initialisierung. Vorzugsweise würde ich gerne eine Kopie der va_list für die Verwendung mit vsnprintf.
Ich habe getan, einige der Forschung zu tun und fand ein paar Möglichkeiten. Einige von denen, die ich Frage, ob es eine entsprechende Methode (in Bezug auf die stabile und portable).
- Könnten Sie eine bessere Beschreibung was du meinst mit "später"? Ich denke, es sollte ziemlich klar sein, dass jemand 'va_list' kann nur so lange gültig, wie die entsprechende Variable Funktion Aufruf noch aktiv ist (d.h. von den low-level, von der Implementierung abhängige Sicht, solange die entsprechenden stack-frame mit Parametern ist lebendig). Alle versuche, darauf zuzugreifen, nachdem die Funktion zurückgekehrt ist, ist ein Rezept für eine Katastrophe.
- die Verwendung von Boost.Format stattdessen erstellen Sie die Zeichenfolge. Es gibt keinen Grund, es zu sprengen, geben Sie Sicherheit, wenn Sie es vermeiden können.
- Ja, wir sind gehen, um am Ende etwas zu tun ähnlich wie diese, weil diese Methode (die in der Frage) ist schlicht mangelhaft.
- Ich würde nicht schreiben "fehlerhaft." Ich würde schreiben "Umsetzung abhängig." 😉 Ich wünschte, jemand würde versuchen, die Mac-compiler mit dem code, den ich gepostet. Ich bin mal gespannt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Speicherung der
va_list
selbst ist keine gute Idee; der standard erfordert nur, dass dieva_list
argument arbeiten mitva_start()
,va_arg()
undva_end()
. Soweit ich das beurteilen kann, derva_list
ist nicht garantiert, kopieren constructable.Aber Sie brauchen nicht zu speichern, die
va_list
. Kopieren Sie die angegebenen Argumente in eine andere Datenstruktur wie einen Vektor (void*, wahrscheinlich), und rufen Sie Sie später in der üblichen Weise. Sie müssen vorsichtig sein, über die Arten, aber das ist immer der Fall für die printf-Stil-Funktionen in C++.Diese Frage hat wirklich hat mein Interesse geweckt. Auch werde ich vor einem ähnlichen problem in meiner eigenen Arbeit, so ist die Lösung erarbeitet, hier kann mir helfen,, auch.
Kurz gesagt, schrieb ich eine proof-of-concept-code, welche caches variable Argumente für die spätere Verwendung-Sie finden es unten.
Konnte ich den code unten, um korrekt zu arbeiten auf Windows-und intel-basierten Linux. Ich kompiliert mit gcc auf Linux und Microsoft Visual C ++ auf Windows. Es ist eine zweimal wiederholte Warnung vor Missbrauch von va_start() von gcc -- die Warnung könnten Sie deaktivieren in Ihrem makefile.
Ich würde gerne wissen, ob dieser code funktioniert auf einem Mac-compiler. Es könnte ein wenig Feintuning, um es zu kompilieren.
Ich weiß, das code ist:
Meine Verwendung von malloc() und free() war sehr bewusst, wie Makros va_list sind aus dem C-standard und nicht C++ - Funktionen. Ich merke, deine Frage-Titel erwähnt C++, aber ich habe versucht, produzieren eine voll C-kompatible Lösung, andere als mit einem C++-style Kommentare.
Dieser code wird auch ohne Zweifel einige bugs hat oder nicht-portabilities im format-string Verarbeitung. Ich biete diese als proof-of-concept, die ich gehackt zusammen in zwei Stunden, nicht ein fertiges code-Beispiel bereit für den professionellen Einsatz.
Dass Haftungsausschluss gesagt, ich hoffe, Sie finden das Ergebnis so schön wie ich! Das war eine schöne Frage zu hacken um in. Die Kranken und verdrehten Natur des Ergebnis gibt mir eine Tiefe Bauch-lachen. 😉
Können Sie
va_copy()
hier ein Beispiel:Was Sie beschreiben, über "holding die Nummer(N) in der va_list" ist der Weg, dies zu nähern.
Den
va_list
verwaltet Zeiger auf den temporären Speicher auf dem stack (sogenannte "automatische Speicherung" in der C-standard). Nachdem die Funktion mit der variable args zurückgegeben hat, ist diese automatische Speicherung ist Weg und die Inhalte sind nicht mehr nutzbar. Aufgrund dieser, Sie können nicht einfach eine Kopie derva_list
selbst-der Speicher, auf den es verweist enthält unberechenbar Inhalt.In dem Beispiel, das Sie geben, benötigen Sie zum speichern von zwei Ganzzahlen, die erneut verwendet werden, wenn neu zu erstellen, die Nachricht. Je nachdem, wie viele verschiedene format-strings, die Sie zu bewältigen haben, Ihren Ansatz zu variieren.
Für eine ganz Allgemeine Art von Ansatz, müssen Sie zu:
cache_arguments()
" - Funktion schafft einen dynamischen-Speicher-Puffer auf die Gefundene Werte in variable Argumente.cache_arguments()
möchten, verwenden Sie dieprintf()
-Stil-format-string zusammen mit derva_start
,va_arg
,va_end
Makros. Sie müssen zum abrufen der Typen nach derprintf()
Typ-Bezeichner, weilsizeof(double) != sizeof(int)
.va_arg()
auf Ihrer Plattform. (Lesen Sie Ihrevarargs.h
- Datei).vsnprintf()
Arbeit mit diesem Cache-Speicher-Puffer anstelle von einem Zeiger erstellt vonva_start()
.Oben genannten Elemente sind alle möglich, auf den meisten Plattformen, einschließlich Linux und Windows.
Ein Element, möchten Sie vielleicht zu berücksichtigen, die über die übersetzung ist die Wort-Reihenfolge Anliegen. Was ist in Englisch geschrieben werden als:
Konnte in einigen (menschlichen) Sprachen, die nur geschrieben werden fließend, mit einem Wort, um analagous zu:
Aus diesem Grund, die Win32
FormatMessage()
- API verwendet eineprintf()
-wie format-string, mit der funktionelle Unterschied, dass die Parameter sind nummeriert, in:(Der string-Typ ist davon ausgegangen, für jedes argument, so
%1
entspricht%1!s!
)Natürlich können Sie nicht mit der Win32-API, aber die Funktionalität der Veränderung der Wort-Reihenfolge der Argumente formatiert ist, was ich bin versucht, vorzustellen, wie ein Konzept. Möchten Sie vielleicht implementieren Sie diese in Ihrer software, auch.
Den Weg, es zu tun in C ist das senden einer struct Argumente an die Funktion statt. Sie sollten übergeben, die struct-by reference und dann kopieren (memcpy) die struct zu einer gemeinsamen Position, die Ihnen erlauben, um es wiederverwenden später. Sie enträtseln die Struktur an das Ziel in der gleichen Art und Weise Sie es geschickt. Sie halten die Vorlage der struct für die Einstellung und immer".