2010-10-24 28 views
4

Est-il possible d'écrire une macro (en utilisant la concaténation de jetons) qui renvoie le format pour printf? E.g.Macro C pour générer une chaîne au format printf

#define STR_FMT(x) ...code-here... 

STR_FMT(10) se développe pour "%10s"

STR_FMT(15) se développe pour "%15s"

... etc.

Alors que je peux utiliser cette macro dans un printf:

printf(STR_FMT(10), "*"); 

Répondre

12

Vous pouvez, mais je pense qu'il pourrait être préférable d'utiliser la capacité printf() doit spécifier la taille du champ et/ou précision dynamique:

#include <stdio.h> 

int main(int argc, char* argv[]) 
{ 
    // specify the field size dynamically 
    printf(":%*s:\n", 10, "*"); 
    printf(":%*s:\n", 15, "*"); 

    // specify the precision dynamically 
    printf("%.*s\n", 10, "******************************************"); 
    printf("%.*s\n", 15, "******************************************"); 

    return 0; 
} 

Ceci a l'avantage de ne pas utiliser le préprocesseur et sera également laissez-vous utiliser des variables ou des fonctions pour spécifier la largeur du champ au lieu des littéraux.


Si vous décidez d'utiliser des macros à la place, s'il vous plaît utiliser l'opérateur # indirectement (et l'opérateur ## si vous l'utilisez ailleurs) comme ceci:

// macros to allow safer use of the # and ## operators 
#ifndef STRINGIFY 
#define STRINGIFY2(x) #x 
#define STRINGIFY(x) STRINGIFY2(x) 
#endif 

#define STR_FMTB(x) "%" STRINGIFY(x) "s" 

Sinon, si vous décidez d'utiliser des macros pour spécifier la largeur du champ, vous obtiendrez un comportement indésirable (comme décrit dans What are the applications of the ## preprocessor operator and gotchas to consider?).

+2

Je l'avouerais deux fois si je le pouvais. –

+1

+1 pour mentionner '% *', et déterminer que OP souhaite probablement transmettre des variables et non des constantes de compilation à cette macro. –

7
#define STR_FMT(x) "%" #x "s" 
+0

Je vais supprimer ma réponse;) – AraK