jfs
Por ejemplo, ¿cómo puedo evitar escribir el ‘func_name’ dos veces?
#ifndef TEST_FUN
# define TEST_FUN func_name
# define TEST_FUN_NAME "func_name"
#endif
me gustaria seguir el Punto único de la verdad regla.
Versión del preprocesador C:
cpp --version
Producción:
cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
jonathan leffler
El que es tímido* te di el germen de una respuesta, pero sólo el germen. La técnica básica para convertir un valor en una cadena en el preprocesador de C es, de hecho, a través del operador ‘#’, pero una simple transliteración de la solución propuesta genera un error de compilación:
#define TEST_FUNC test_func
#define TEST_FUNC_NAME #TEST_FUNC
#include <stdio.h>
int main(void)
{
puts(TEST_FUNC_NAME);
return(0);
}
El error de sintaxis está en la línea ‘puts ()’; el problema es un ‘# extraviado’ en la fuente.
En la sección 6.10.3.2 del estándar C, ‘El operador #’, dice:
Cada # token de preprocesamiento en la lista de reemplazo para una macro similar a una función debe ir seguido de un parámetro como el siguiente token de preprocesamiento en la lista de reemplazo.
El problema es que puede convertir argumentos macro en cadenas, pero no puede convertir elementos aleatorios que no sean argumentos macro.
Por lo tanto, para lograr el efecto que buscas, sin duda tienes que hacer un poco de trabajo 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);
}
No tengo completamente claro cómo planea usar las macros y cómo planea evitar la repetición por completo. Este ejemplo un poco más elaborado podría ser más informativo. El uso de una macro equivalente a STR_VALUE es un modismo necesario para obtener el resultado deseado.
#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);
}
* En el momento en que se escribió esta respuesta por primera vez, el nombre de shoosh usaba ‘Shy’ como parte del nombre.
-
Reescritura casi literal de un comentario hecho originalmente el 2012-10-12 21:37 (que mostraba una negrita función en lugar de
__func__
) — Por supuesto, en C99, podríamos usar el__func__
identificador predefinido en la función para indicar el nombre de la función. Sin embargo, eso no es ayuda fuera de la función, y ahí es donde realmente se necesita la cadena del nombre de la función.–Jonathan Leffler
29 de diciembre de 2013 a las 18:17
jfs
La solución de Jonathan Leffler funciona.
Un ejemplo de trabajo 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;
}
Ejemplo:
gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
Producción:
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;
}
Referencia: Wikipedia preprocesador C página
Posible duplicado de C Macros para crear cadenas
– Richard Stelling
06/10/2015 a las 10:34