Ricardo
En la línea de comando de GCC, quiero definir una cadena como -Dname=Mary
. Luego, en el código fuente, quiero printf("%s", name);
imprimir Mary
.
¿Cómo podría hacerlo?
Dos opciones. Primero, escapa de las comillas para que el caparazón no las coma:
gcc -Dname=\"Mary\"
O, si realmente quieres -Dname=Mary, puedes encadenarlo, aunque es un poco raro.
#include <stdio.h>
#define STRINGIZE(x) #x
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
int main(int argc, char *argv[])
{
printf("%s", STRINGIZE_VALUE_OF(name));
}
Tenga en cuenta que STRINGIZE_VALUE_OF felizmente evaluará hasta la definición final de una macro.
-
muchas gracias arturo debes ser un experto en C. otra pregunta: prefiero la segunda opción. cuando uso STRINGIZE_VALUE_OF(nombre), lo traduce a “1”, en el caso de que tenga gcc -Dname=Mary -DMary. ¿Hay alguna forma de dejar que gcc deje de interpretar a Mary?
– Ricardo
9 de marzo de 2010 a las 19:24
-
Richard, después de mucha revisión, no creo que pueda encontrar una forma que funcione en el ejemplo anterior. Desafortunadamente, sus opciones son ninguna expansión (por ejemplo, le da “nombre”) y una expansión completa (por ejemplo, nombre->Mary->1 si Mary se define como 1). Dependiendo de su caso de uso exacto, puede haber formas de evitar esto, si Mary puede convertirse en un const int en lugar de una definición, por ejemplo.
–Arthur Shipkowski
10 de marzo de 2010 a las 2:53
-
¿Alguien puede dar una razón de por qué necesita usar macros de stringificación anidadas como esa? Parece que el resultado debería ser el mismo, pero llamar a STRINGIZE_VALUE_OF() parece forzar la expansión macro del argumento, mientras que STRINGIZE() no lo hace.
– Ionoclasta Brigham
13/03/2014 a las 23:52
-
@IonoclastBrigham, no vi esto hasta hoy. Parte de esto es que a veces desea convertir en cadenas las palabras vacías; por ejemplo, en muchos casos, stringize se usa para implementar assert() de modo que pueda imprimir la expresión exacta que tiene, en cuyo caso desea tener macros sin expandir. Una vez que te das cuenta de que un stringize base funciona de esa manera, el anidamiento fuerza una segunda ronda de expansión macro.
–Arthur Shipkowski
9 de noviembre de 2014 a las 23:57
-
La segunda opción es el camino a seguir si no puedes pasar [double quote] como parámetro. En mi caso, tengo gitlab CI llamando a powershell llamando a un .exe compilado desde eclipse (java). Tantas interpretaciones antes de llamar a gcc, por lo que es más fácil manejarlo en el código C al final.
– ofaurax
7 sep 2022 a las 8:52
John
Para evitar que el shell “coma” las comillas y otros caracteres, puede probar con comillas simples, como esta:
gcc -o test test.cpp -DNAME='"Mary"'
De esta manera, tiene control total sobre lo que se define (comillas, espacios, caracteres especiales y todo).
psicodelia
La forma más portátil que encontré hasta ahora fue usar \"Mary\"
. Funcionará no solo con GCC, sino con cualquier otro compilador de C. Por ejemplo, si intenta utilizar /Dname=""Mary""
con un compilador de Microsoft, se detendrá con un error, pero /Dname=\"Mary\"
trabajará.
En Ubuntu estaba usando un alias que define CFLAGS, y CFLAGS incluía una macro que define una cadena, y luego uso CFLAGS en un Makefile. Tuve que escapar de los caracteres de comillas dobles y también de los caracteres \. Se veía algo como esto:
CFLAGS='" -DMYPATH=\\\"/home/root\\\" "'
Esta es mi solución para: -DUSB_PRODUCT=\""Arduino Leonardo\""
Lo usé en un archivo MAKE con:
GNU Make 3.81 (de GnuWin32)
y
avr-g++ (AVR_8_bit_GNU_Toolchain_3.5.0_1662) 4.9.2
El resultado en un archivo precompilado (opción -E para g++) es:
const u8 STRING_PRODUCT[] __attribute__((__progmem__)) = "Arduino Leonardo";
Hossein
Aquí hay un ejemplo simple:
#include <stdio.h>
#define A B+20
#define B 10
int main()
{
#ifdef __DEBUG__
printf("__DEBUG__ DEFINED\n");
printf("%d\n",A);
#else
printf("__DEBUG__ not defined\n");
printf("%d\n",B);
#endif
return 0;
}
Si compilo:
$gcc test.c
Producción:
__DEBUG__ not defined
10
Si compilo:
$gcc -D __DEBUG__ test.c
Producción:
__DEBUG__ defined
30
eh
FYI: Aparentemente, incluso diferentes versiones de la misma cadena de herramientas en el mismo sistema pueden actuar de manera diferente en este sentido… (Como en, sería parecer esto sería un problema de paso de caparazón, pero aparentemente no se limita solo al caparazón).
Aquí tenemos xc32-gcc 4.8.3 vs. (avr-)gcc 4.7.2 (y varios otros) usando el mismo makefile y main.c, la única diferencia es 'make CC=xc32-gcc'
etc.
CFLAGS += -D'THING="$(THINGDIR)/thing.h"'
ha estado en uso en muchos versiones de gcc (y bash) durante varios años.
Para hacer esto compatible con xc32-gcc (y a la luz de otro comentario que afirma que \” es más portátil que ‘”), se tuvo que hacer lo siguiente:
CFLAGS += -DTHING=\"$(THINGDIR)/thing.h\"
ifeq "$(CC)" "xc32-gcc"
CFLAGS := $(subst \",\\\",$(CFLAGS))
endif
hacer cosas en realidad confuso al descubrir esto: aparentemente una -D sin comillas con // da como resultado un #define con un comentario al final… por ejemplo
THINGDIR=/thingDir/
-> #define /thingDir//thing.h
-> #define /thingDir
(Gracias por la ayuda de la respuestas aquí, por cierto).
Le recomiendo encarecidamente que utilice mayúsculas (
-DNAME=\"Mary\"
) para tokens que va a definir de esta manera, para que se vean como otras macros.– JSB
9 de marzo de 2010 a las 17:22
La macro en la pregunta de cadena: stackoverflow.com/questions/240353/…
– Ciro Santilli OurBigBook.com
06/10/2015 a las 19:37