8
votes

#define et fonctions avec des arguments de longueur variable

J'ai des zillions de my_printf () appels de fonction dans un vaste programme. Je veux maintenant les convertir, de sorte que la fonction prend un nouvel argument entier (appelez-le x) sans avoir à modifier les zillions des appels. Si my_printf n'a jamais pris exactement un argument de chaîne, je pourrais faire quelque chose comme ceci:

#if BELT_AND_BRACES_DIAGNOSTIC_MODE
    #define function(x) _function(__FILE__,__LINE__,x)
#else // speed critical optimised mode
    #define function(x) _function(x)
#endif

#if BELT_AND_BRACES_DIAGNOSTIC_MODE
    void _function(char *file,int line,int x)
#else
    void _function(int x)
#endif
{
    // stuff
    #if BELT_AND_BRACES_DIAGNOSTIC_MODE
    if (something_went_wrong)
    {
        printf("Cock up in function when called from %s line %d\n",file,line);
    }
    #endif
}

c

0 commentaires

6 Réponses :


7
votes

La meilleure chose à faire est bien sûr de mordre la balle et de modifier le code. Sinon, vous créez un "mystère", qui doit être résolu par tous les futurs responsables du code. Même si ce n'est que vous, c'est exactement le genre d'astuce intelligente que vous oublierez tout. Ça suce de revenir et d'être perplexe par d'étranges macros apparentes inutiles.

Cela dit, si vous utilisez une boîte à outils GNU, vous pouvez peut-être examiner en utilisant Varargs Macros .


2 commentaires

+1 pour mordre la balle. Avec les éditeurs d'aujourd'hui avec un support de refactoring, etc., vous devriez vous rire. Heck, mon éditeur de programmation Il y a 15 ans pourrait facilement effectuer une recherche globale et remplacer les fichiers spécifiés par Wildcard sur un arborescence de répertoire entier, avec et sans mes prévisualiser les résultats en premier. (Et si vous pensez macro, vous pouvez simplement le faire aveugle.)


+1. Regardez-le comme une opportunité d'apprentissage pour vraiment vous accéder à ce qu'un éditeur moderne peut faire (ou si vous êtes assez long, quel vim ou vos emacs peuvent faire - et ils peuvent faire des choses que Visual Studio ne fait que attraper avec ...).



9
votes

Si le code peut être compilé sous forme de code C99, vous pouvez définir un macro variable

#define my_printf(str, args...) _my_printf(x, str, ##__VA_ARGS__)


8 commentaires

C'est GNU, pas C99 - la version C99 lirait définir mon_printf (str, ...) _my_printf (x, __va_args __) ; Gardez à l'esprit que vous devez fournir un argument au lent


De plus, vous et moi oubliés de passer sur str ; Je pense que la meilleure approche serait de supprimer le str entièrement et simplement d'utiliser définir mon_printf (...) _my_printf (x, __va_args __) afin que vous puissiez l'appeler sans La fonction de la fonction même dans la version C99


Le problème est maintenant résolu. J'utilise Dev-Studio 2008 et la chose VA_ARGS a fonctionné un traitement - mais je ne suis pas sûr de quelle réponse à la marque est correcte, car aucun d'entre eux ne sont vraiment compensés. La réponse de Dwind implique que je dois utiliser GNU et la réponse de Phillipe ont aussi des erreurs.


@Mick: J'ai ajouté une réponse avec quelques détails sur le problème avec les listes d'arguments vides et les virgules suivantes: Stackoverflow.com/questions/1491749/...


Strangement assez de GCC compilé la formulaire ## args avec STD = C99; Je pensais que cela supprima les extensions GNU (Onlt Tetsed avec GCC V3.4.3). Merci, je l'ai réparé.


@Philippe: utilisez -std = c99 -pedantique pour obtenir les avertissements


Je devais remplacer ## VA_ARGS par # SARGS pour faire ce travail.


@jbochi quel compilateur utilisez-vous?



0
votes

si my_printf prend déjà un nombre variable d'arguments, je ne sais pas pourquoi vous devez envelopper "un autre argument" dans une macro ... insérez simplement les nouveaux appels avec l'argument supplémentaire et être fait avec elle; Les anciens appels devraient toujours fonctionner comme prévu.


0 commentaires

2
votes

pas avec des macros C89 standard, vous ne pouvez pas. Cependant, vous pouvez obtenir le même effet à l'aide de fonctions, en rompant la partie principale de votre My_Printf dans une fonction vmy_printf , analagous dans la norme vprintf : xxx

(ce genre de chose est pourquoi ces vidéations de toutes les fonctions de varargs standard existent.)


0 commentaires

9
votes

Vous pouvez utiliser C99 variadic macros: xxx

comme Mise en œuvre de Microsoft Les virgules suivantes, l'argument STR peut être ajouté explicitement xxx

mais ceci conduirait à une erreur de syntaxe dans la norme C lorsqu'il serait appelé sans arguments variadiques xxx

ou une liste d'arguments vide xxx donc

donc , J'irais avec la première version.


0 commentaires

0
votes

Une solution simple à ce problème est ...

my_printf((any number of arguments))


0 commentaires