J'utilise un va_list pour construire une chaîne qui est rendu.
"Player Score:%d"
5 Réponses :
stocker le Mais vous n'avez pas besoin de stocker le va_list code> n'est pas une bonne idée; La norme nécessite uniquement que l'argument
va_list code> fonctionne avec
va_start () code>,
va_arg () code> et
va_end () code>. Autant que je puisse dire, le
va_list code> n'est pas garanti d'être copier constructible. P>
va_list code>. Copiez les arguments fournis dans une autre structure de données, telle qu'un vecteur (de vide *, probablement) et les récupérer ultérieurement de la manière habituelle. Vous devrez faire attention aux types, mais c'est toujours le cas pour les fonctions de style Printf en C ++. P>
Je me suis demandé de la copie constructible / des qualités assignables de Va_List. Je n'arrive pas à trouver une discussion dans la norme.
Ce serait parce qu'il est mise en œuvre suppose spécifique I. Je sais que certains processeurs qui stockent les premiers arguments dans les registres au lieu d'une pile, ce qui rendrait la copie du va_list un peu plus compliqué. En outre, va_list ne sait pas combien il y a des arguments. Vous avez vraiment besoin d'une structure qui contient des informations de quantité, simple accès aléatoire et la sémantique de copie bien définies. Certaines langues peuvent exiger des arguments dans un ordre différent!
Ce que vous décrivez sur "Holding the Number (s) fourni dans la Va_List" est le moyen de l'approcher. P>
Le Dans l'exemple que vous donnez, vous devrez stocker deux entiers réutilisés lors de la ré-création de ce message. En fonction du nombre de cordes de format différents que vous devez faire face, votre approche pourrait varier. P>
Pour un type d'approche totalement général, vous devrez: P>
Les éléments ci-dessus sont tous possibles sur la plupart des plates-formes, y compris Linux et Windows. P>
Un article que vous souhaiterais envisager de la traduction est la préoccupation de mot-ordonnance. Ce qui est écrit en anglais comme suit: p>
joueur Sam a marqué 20 points. P>
blockQuote>
pourrait dans certaines langues (humaines) seulement être écrites couramment avec un ordre de mot analagous à: p>
20 points ont été marqués par le joueur Sam. P>
blockQuote>
Pour cette raison, le Win32 Le joueur% 1 a marqué% 2! D! Points. (le type de chaîne est supposé pour chaque argument, de sorte que Bien sûr, vous ne pouvez pas utiliser l'API Win32, mais la fonctionnalité de modification de l'ordre des mots des arguments formatés est ce que je tente d'introduire en tant que concept. Vous voudrez peut-être implémenter cela dans votre logiciel, également. P> va_list code> maintient les pointeurs à la mémoire temporaire sur la pile (appelé "stockage automatique" dans la norme C). Une fois la fonction de variable args renvoyée, ce stockage automatique est parti et le contenu n'est plus utilisable. Pour cette raison, vous ne pouvez pas simplement conserver une copie du
VA_List CODE> - La mémoire IT Les références contiennent du contenu imprévisible. P>
cache_arguments () code>" Fonction qui crée un tampon de mémoire dynamique des valeurs trouvées dans les arguments variables. LI>
cache_arguments () code> utiliserait la chaîne
printf () code> -Style, ainsi que le
va_start code>,
va_arg Code>,
va_end code> macros. Vous devrez récupérer les types selon les spécificateurs de type
printf () code>, car
tailleOf (double)! = Tailleof (int) code>. Li>.
VA_ARG () CODE> sur votre plate-forme. (Lisez votre
varargs.h code> fichier.) Li>
VSNPRINTF () CODE> Utilisation de ce tampon de mémoire mis en cache au lieu d'un pointeur créé par
VA_START () CODE>. LI>.
ul>
FormatMessage () Code> API utilise un
printf () code> String de format, avec la différence fonctionnelle que les paramètres sont numérotés, comme dans: < / p>
% 2! D! Les points ont été marqués par le joueur% 1. P>
blockQuote>
% 1 code> est équivalent à
% 1! S! code>) p>)
Vous montrez un point complètement valide à la fin là-bas, j'aurais simplement dû fournir un exemple avec seulement un% de la chaîne source. Ainsi, le format d'une norme Va_List une fois que vous avez démarré afin que je puisse envoyer dans un tampon que j'ai créé (via cache_arguments) dans VSPRINTF. Je veux juste m'assurer que je vous comprends correctement. Cela doit fonctionner sur Windows, Linux et Mac. Si non, je devrai simplement faire mon propre printf qui prend un vecteur de valeurs que je stocke par opposition à un ....
La mise en œuvre de VA_LIST n'est pas standard, mais la valeur renvoyée de VA_ARG () est. Pour former la mémoire requise, effectuez une «course d'essai» à travers les arguments sans lire leurs valeurs. Utilisez VA_ARG () pour renvoyer leurs adresses. Vous devrez appeler VA_ARG () un temps supplémentaire pour récupérer un caractère final imaginaire. En soustrayant la valeur de retour finale de VA_ARG () à partir de l'initiale, vous pouvez obtenir le nombre d'octets requis. Allouer ce nombre d'octets + Tailleof (int). Faites une deuxième passe à travers les arguments, en les comportant maintenant au tampon alloué - commencez à Byte Tailleof (int) i>
Ah, oui ... En raison de la mise en œuvre de Va_Start / VA_ARG (renvoyer le contenu d'un pointeur), il sera légal d'utiliser & VA_ARG (AP) sur toutes les plateformes - qui est nécessaire pour obtenir les adresses de paramètres.
Cette question a vraiment piqué mon intérêt. De plus, je serai confronté à un problème similaire dans mon propre travail, de sorte que la solution conçue ici peut aussi m'aider aussi.
En bref, j'ai écrit un code de la preuve de concept qui met en cache des arguments variables pour une utilisation ultérieure - vous pouvez trouver Ci-dessous. P>
J'ai pu obtenir le code ci-dessous pour fonctionner correctement sur Windows et Intel basé sur Linux. J'ai compilé avec GCC sur Linux et MSVC sous Windows. Il y a un avertissement répété à deux reprises sur l'abus de VA_START () de GCC - ce qui avertit que vous pourriez désactiver dans votre maquillage. P>
J'aimerais savoir si ce code fonctionne sur un compilateur Mac. Cela pourrait prendre un peu de peaufie pour l'obtenir pour compiler. P>
Je réalise que ce code est: p>
Mon utilisation de MALLOC () et GRATUIT () était très délibérée, car Va_List Macros provient de la norme C et ne sont pas des fonctionnalités C ++. Je réalise votre titre de question mention C ++, mais j'ai essayé de produire une solution entièrement compatible C, autre que d'utiliser certains commentaires de style C ++. P>
Ce code a aussi des bugs ou des non-portabilités dans le traitement de la chaîne de format. Je fournis cela comme une preuve de concept que j'ai piraté ensemble en deux heures et non un échantillon de code fini prêt à être utilisé pour un usage professionnel. P>
Cet avis de non-responsabilité a dit que vous trouverez le résultat aussi agréable que je l'ai fait! C'était une belle question à pirater. La nature malade et tordue du résultat me donne un rire de ventre profond. ;) p>
Je pense que c'est une longue et compliquée pour des tâches simples. Je ne sais pas exactement ce que votre extrait est servi, cela pourrait faire et maintenir d'autres fonctionnalités, mais j'ai fait une simple allocation / stockage pour les valeurs AGRRS. `Args f2_args = (args i>) MALLOC (1 * TAILLEOF (INT8_T) + 1 * Tailleof (uint8_T) + 1 * Tailleof (int) + 1 * Taille de taille (Cons-Char *)); // Initialisation args f2_args = (args) {(int8_t) -10, (uint8_t) 9, (int) 90000, (const Char i>) p0}; `Ce que vous pensez?
Vous pouvez utiliser va_copy () code>, voici un exemple:
Le mot clé de la question était "utilisé ultérieur". Une fois la fonction renvoie, les variables TMP et AP ne peuvent pas être utilisées.
Le moyen de le faire en C est d'envoyer une structure d'arguments à la fonction à la place. Vous devez transmettre la structure par référence, puis copier (memcpy) la structure vers un emplacement commun qui vous permettra de la réutiliser plus tard. Vous démêlez la structure à la destination de la même manière que vous l'avez envoyée. Vous gardez le gabarit de la structure pour «régler et obtenir». P>
Pourriez-vous fournir une meilleure description de ce que vous entendez par «plus tard»? Je pense qu'il devrait être assez clair pour quiconque que "Va_List" ne peut être valide que tant que l'invocation de fonction variable correspondante est toujours active (c'est-à-dire du point de vue dépendant de la mise en oeuvre de bas niveau, tant que le cadre de pile correspondant avec des paramètres est vivant). Toute tentative d'y accéder une fois que la fonction est renvoyée est une recette de catastrophe.
l'utilisation Boost.Format au lieu de construire la chaîne. Il n'y a aucune raison de faire sauter la sécurité de type si vous pouvez l'éviter.
Oui, nous allons finir par faire quelque chose de similaire à cela, car cette méthode (celle de la question) est tout simplement imparfaite.
Je n'écrirais pas "défectueux". J'écrirais "la mise en œuvre dépendante". ;) Je souhaite que quelqu'un essaierait le compilateur Mac avec le code que j'ai posté. Je suis curieux.