62 votes

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 le Point unique de vérité règle.

Version du préprocesseur C :

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

89voto

Jonathan Leffler Points 299946

Celui qui est timide * vous a donné le germe d'une respuesta mais seulement le germe. La technique de base pour convertir une valeur en chaîne de caractères dans le préprocesseur C est en effet via l'opérateur '#', mais une simple translittération de la solution proposée obtient une erreur de compilation :

#define TEST_FUNC test_func
#define TEST_FUNC_NAME #TEST_FUNC

#include <stdio.h>
int main(void)
{
    puts(TEST_FUNC_NAME);
    return(0);
}

L'erreur de syntaxe se trouve sur la ligne 'puts()' - 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 de remplacement d'une macro de type fonction de type fonction doit être suivi d'un paramètre en tant qu'élément de prétraitement suivant dans la liste de remplacement de la fonction liste de remplacement.

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

Ainsi, pour obtenir l'effet recherché, vous devez certainement faire un travail supplémentaire.

#define FUNCTION_NAME(name) #name
#define TEST_FUNC_NAME  FUNCTION_NAME(test_func)

#include <stdio.h>

int main(void)
{
    puts(TEST_FUNC_NAME);
    return(0);
}

Je ne comprends pas très bien comment vous comptez utiliser les macros et comment vous comptez éviter les répétitions. Cet exemple un peu plus élaboré pourrait être plus instructif. L'utilisation d'une macro équivalente à STR_VALUE est une idiome qui est 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 <stdio.h>

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, shoosh Le nom de l'enfant a utilisé "Shy" comme partie du nom.

22voto

J.F. Sebastian Points 102961

@Jonathan Leffler : Merci. Votre solution fonctionne.

Un exemple complet de fonctionnement :

/** compile-time dispatch 

   $ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
*/
#include <stdio.h>

#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

0voto

Jason Weathered Points 5346
#include <stdio.h>

#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 : Wikipédia Préprocesseur C page

-1voto

shoosh Points 34322

#define TEST_FUN_NAME #FUNC_NAME

voir aquí

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X