Come creare una stringa di caratteri dal valore di una macro C?
-
10-07-2019 - |
Domanda
Ad esempio, come evitare di scrivere due volte il nome_funzione?
#ifndef TEST_FUN
# define TEST_FUN func_name
# define TEST_FUN_NAME "func_name"
#endif
Mi piacerebbe seguire la Single Point of Truth .
Versione del preprocessore C:
$ cpp --version
cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
Soluzione
Chi è timido * ti ha dato il germe di un answer , ma solo il germe. La tecnica di base per convertire un valore in una stringa nel pre-processore C è in effetti tramite l'operatore '#', ma una semplice traslitterazione della soluzione proposta ottiene un errore di compilazione:
#define TEST_FUNC test_func
#define TEST_FUNC_NAME #TEST_FUNC
#include <stdio.h>
int main(void)
{
puts(TEST_FUNC_NAME);
return(0);
}
L'errore di sintassi si trova sulla riga 'put ()' - il problema è un '# randagio' nell'origine.
Nella sezione 6.10.3.2 della norma C, 'L'operatore #', dice:
Ogni # token di preelaborazione nel file elenco di sostituzione per una funzione simile la macro deve essere seguita da un parametro come token di preelaborazione successivo nel file elenco di sostituzione.
Il problema è che puoi convertire argomenti macro in stringhe, ma non puoi convertire elementi casuali che non sono argomenti macro.
Quindi, per ottenere l'effetto che stai cercando, devi sicuramente fare un lavoro extra.
#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);
}
Non sono del tutto chiaro su come prevedi di utilizzare le macro e su come prevedi di evitare del tutto la ripetizione. Questo esempio leggermente più elaborato potrebbe essere più informativo. L'uso di una macro equivalente a STR_VALUE è un linguaggio necessario per ottenere il risultato desiderato.
#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);
}
* Nel momento in cui questa risposta è stata scritta per la prima volta, il nome di shoosh ha usato 'Timido' come parte del nome.
Altri suggerimenti
@Jonathan Leffler: Grazie. La tua soluzione funziona.
Un esempio funzionante completo:
/** 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;
}
Esempio:
$ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
do something else
TEST_FUN_NAME=another_func
#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;
}
Riferimento: pagina C preprocessore di Wikipedia
#define TEST_FUN_NAME #FUNC_NAME
vedi qui