Comment faire une chaîne de caractères à partir de la valeur d’une macro C?

Par exemple, comment éviter d’écrire deux fois le ‘func_name’?

#ifndef TEST_FUN # define TEST_FUN func_name # define TEST_FUN_NAME "func_name" #endif 

J’aimerais suivre la règle du sharepoint vérité unique.

Version du préprocesseur C:

 $ cpp --version cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14) 

Celui qui est timide * vous a donné le germe d’une réponse , mais seulement le germe. La technique de base pour convertir une valeur en chaîne dans le pré-processeur C est bien via l’opérateur “#”, mais une simple translittération de la solution proposée génère une erreur de compilation:

 #define TEST_FUNC test_func #define TEST_FUNC_NAME #TEST_FUNC #include  int main(void) { puts(TEST_FUNC_NAME); return(0); } 

L’erreur de syntaxe est sur la ligne ‘(()’) – le problème est un ‘stray #’ dans la source.

Dans la section 6.10.3.2 de la norme C, «L’opérateur #», il est dit:

Chaque jeton de prétraitement # dans la liste de remplacement pour une macro de type fonction sera suivi d’un paramètre en tant que jeton de prétraitement suivant dans la liste de remplacement.

Le problème est que vous pouvez convertir des arguments de macro en chaînes – mais vous ne pouvez pas convertir des éléments aléatoires qui ne sont pas des arguments de macro.

Donc, pour obtenir l’effet que vous recherchez, vous devez certainement faire un travail supplémentaire.

 #define FUNCTION_NAME(name) #name #define TEST_FUNC_NAME FUNCTION_NAME(test_func) #include  int main(void) { puts(TEST_FUNC_NAME); return(0); } 

Je ne comprends pas très bien comment vous prévoyez d’utiliser les macros et comment vous prévoyez d’éviter les répétitions. Cet exemple légèrement plus élaboré pourrait être plus instructif. L’utilisation d’une macro équivalente à STR_VALUE est un idiome nécessaire pour obtenir le résultat souhaité.

 #define STR_VALUE(arg) #arg #define FUNCTION_NAME(name) STR_VALUE(name) #define TEST_FUNC test_func #define TEST_FUNC_NAME FUNCTION_NAME(TEST_FUNC) #include  static void TEST_FUNC(void) { printf("In function %s\n", TEST_FUNC_NAME); } int main(void) { puts(TEST_FUNC_NAME); TEST_FUNC(); return(0); } 

* Au moment où cette réponse a été écrite pour la première fois, le nom de shoosh utilisait ‘Shy’ dans le nom.

@ Jonathan Leffler: Merci. Votre solution fonctionne

Un exemple de travail complet:

 /** comstack-time dispatch $ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub */ #include  #define QUOTE(name) #name #define STR(macro) QUOTE(macro) #ifndef TEST_FUN # define TEST_FUN some_func #endif #define TEST_FUN_NAME STR(TEST_FUN) void some_func(void) { printf("some_func() called\n"); } void another_func(void) { printf("do something else\n"); } int main(void) { TEST_FUN(); printf("TEST_FUN_NAME=%s\n", TEST_FUN_NAME); return 0; } 

Exemple:

 $ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub do something else TEST_FUN_NAME=another_func 
 #include  #define QUOTEME(x) #x #ifndef TEST_FUN # define TEST_FUN func_name # define TEST_FUN_NAME QUOTEME(TEST_FUN) #endif int main(void) { puts(TEST_FUN_NAME); return 0; } 

Référence: page de préprocesseur C de Wikipedia

#define TEST_FUN_NAME #FUNC_NAME

voir ici