
elomage
Me gustaría imprimir un valor de macro (expandir la macro) en la directiva #warning.
Por ejemplo, para el código:
#define AAA 17
#warning AAA = ???
La salida deseada en tiempo de compilación sería
warning: AAA = 17
¿¿Para qué uso???, o, ¿cómo aumento el código?

moooeeeeep
Puedes usar la directiva del preprocesador #pragma message
.
Ejemplo:
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define AAA 123
#pragma message "content of AAA: " STR(AAA)
int main() { return 0; }
La salida puede verse así:
$ gcc test.c
test.c:5:9: note: #pragma message: content of AAA: 123
#pragma message("content of AAA: " STR(AAA))
^
Para referencia:
Si realmente desea emitir una advertencia, lo siguiente también funcionará. Sin embargo, depende de que C99 esté habilitado (funciona con gcc 4.8.2 o posterior, no probado en versiones anteriores):
#define N 77
#define __STRINGIFY(TEXT) #TEXT
#define __WARNING(TEXT) __STRINGIFY(GCC warning TEXT)
#define WARNING(VALUE) __WARNING(__STRINGIFY(N = VALUE))
#if N == 77
_Pragma (WARNING(N))
#endif
No recomendaría usar #advertencia, ya que no es C estándar. Además, ¿qué es lo que desea advertir pero no arrojar un error? Las advertencias suelen ser algo que el compilador usa cuando está haciendo algo que es sospechoso o completamente peligroso, pero permitido por el estándar C. No tiene tal caso en la aplicación normal, querrá que se compile sin problemas o que no se compile en absoluto. Por lo tanto, usaría #error estándar y no #advertencia no estándar.
No puede escribir el contenido real de la definición del preprocesador. Algo como esto podría ser suficiente:
#if (AAA < SOMETHING) && (AAA > SOMETHING_ELSE)
#error AAA is bad.
#endif
Creo que esto es lo suficientemente detallado para el programador. Sin embargo, si usted De Verdad quiere más detalles y tiene un compilador de C moderno, puede usar afirmación_estática. Entonces puedes lograr algo cercano a lo que quieres:
#include <assert.h>
#define xstr(s) str(s)
#define str(s) #s
#define err_msg(x) #x " is " xstr(x)
#define AAA 17
static_assert(AAA != 17, err_msg(AAA));
este lío de macros debería imprimir AAA es 17. Se puede encontrar una explicación sobre cómo funcionan estas macros aquí.
No estoy seguro de si static_assert se incluyó en C99 o C11, ciertamente está en C11. Es posible que deba usar alguna extensión GCC para habilitarlo.

gilberto
Muchas veces hago que mi Makefile genere un archivo generado localmente que contiene las definiciones deseadas.
generated.h: Makefile
echo >generated.h "// WARNING: generated file. Change Makefile instead"
date >>generated.h '+// generated on %Y-%m-%d %H:%M:%S'
echo >>generated.h "#if AAA == AAA_bad"
echo >>generated.h "#warning \"AAA = $(AAA_bad)\""
echo >>generated.h "#endif"
La necesidad de #include “generated.h” es obvia.
Naturalmente, puede girar cualquier complejidad aquí, pero si se trata de más de unas pocas líneas, es posible que desee poner la complejidad en una secuencia de comandos separada, ya que los Makefiles desordenados pueden ser un problema de mantenimiento horrible. Con un poco de imaginación, puede tener bucles que generen una gran cantidad de pruebas a partir de una pequeña entrada.
Hacer que el destino generado.h dependa de Makefile es fundamental para garantizar que se vuelva a crear el archivo generado si las instrucciones en el destino cambian. Si tiene una secuencia de comandos generada.sh separada, también estaría en la lista de dependencias.
Descargo de responsabilidad: no he probado de verdad.
Otro método simple es, especialmente cuando se trata de un proyecto Makefile (como linux, u-boot, qemu, ..), puede ver el resultado preprocesado del archivo.
Por ejemplo,
para ver el archivo preprocesado de arch/arm64/kernel/head.S
,
puedes hacer hacer arch/arm64/kernel/head.s
. (s pequeña).
para ver el archivo preprocesado de foo/bar/baz.c
,
puedes hacer hacer foo/bar/baz.i
Todas las macros se expanden al valor final.
De acuerdo con el estándar C de 1999, solo tiene
#error
para algo así y no expande ninguna macro, simplemente imprime el texto literalmente y hace que la compilación se detenga. ¿Qué estás tratando de lograr con esto de todos modos?– Alexei Frunze
28 de septiembre de 2012 a las 9:41
Tengo una jerarquía de muchos archivos MAKE que definen AAA de varias maneras, según los parámetros de destino de la marca. Me gustaría verificar que la definición es correcta para el objetivo. Y no quisiera crear una lista de #si AAA = 1… #advertencia “es 1″…
– elomage
28 de septiembre de 2012 a las 9:44
Además, esto es para el mundo incrustado sin pantallas, por lo que no puedo probar fácilmente el valor de la macro agregando algo como printf (#AAA); y comprobarlo en tiempo de ejecución.
– elomage
28 de septiembre de 2012 a las 9:58
Tu también
#if A == 1\#error A = 1\#elif A == 2\#error A = 2\#endif
.– Alexei Frunze
28/09/2012 a las 10:00
@AlexeyFrunze Eso es exactamente lo que quiero evitar: vea mi comentario anterior. Puede que no sepa todos los valores posibles, o puede que haya demasiados.
– elomage
28 de septiembre de 2012 a las 10:09