Concatenar int a string usando C Preprocessor


90

Estoy tratando de averiguar cómo puedo concatenar un #define'd int a un #define' d string usando el preprocesador C. Mi compilador es GCC 4.1 en CentOS 5. La solución también debería funcionar para MinGW.

Me gustaría agregar un número de versión a una cadena, pero la única forma en que puedo hacer que funcione es hacer una copia del número de versión definido como cadenas.

Lo más cercano que pude encontrar fue un método para citar argumentos macro, pero no funciona para #defines

Esto no funciona.

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" #MAJOR_VER #MINOR_VER

Tampoco funciona sin la #s porque los valores son números y se expandiría a "/home/user/.myapp" 2 6, que no es C válido .

Esto funciona, pero no me gusta tener copias de la versión definida porque también las necesito como números.

#define MAJOR_VER 2
#define MINOR_VER 6
#define MAJOR_VER_STR "2"
#define MINOR_VER_STR "6"
#define MY_FILE "/home/user/.myapp" MAJOR_VER_STRING MINOR_VER_STRING

Respuestas:


172

Pregunta clásica del preprocesador C ...

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" STR(MAJOR_VER) STR(MINOR_VER)

El nivel adicional de indirección permitirá al preprocesador expandir las macros antes de que se conviertan en cadenas.


3
STR () en este caso dará una cadena estrecha. ¿Hay alguna variación para convertir esto en una cadena ancha?
gkns

5
No podría decir cuántas veces lo busqué en Google y copié esta respuesta exacta, pero estará en dos dígitos
MightyPork

1
Se requiere el primer "STR_HELPER" porque '#' solo funciona con un argumento macro. Me tomó un tiempo darme cuenta de eso ..
clarkttfu

1
@clarkttfu, una especie de - sí, #solo funciona con argumentos macro. Sin embargo, la STR_HELPERmacro es necesaria para evitar convertir la macro MAJOR_VERen la cadena "MAJOR_VAR", donde queremos que sea el resultado "2".
Lindydancer

13

Una forma de trabajo es escribir MY_FILE como una macro paramétrica:

#define MY_FILE(x,y) "/home..." #x #y

EDITAR: Como señaló "Lindydancer", esta solución no expande las macros en los argumentos. Una solución más general es:

#define MY_FILE_(x,y) "/home..." #x #y
#define MY_FILE(x,y) MY_FILE_(x,y)

1
En mi sincera opinión, esta es la mejor respuesta y es mucho más simple que las otras sugerencias. ¡Me sorprende que no haya obtenido una mejor calificación!
osirisgothra

5
Es una solución limpia que, lamentablemente, no funciona. Si el argumento pasado a MY_FILEson macros, digamos Ay B, esta macro se expandirá a "/home..." "A" "B".
Lindydancer

2

Puedes hacerlo con BOOST_PP_STRINGIZE :

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" BOOST_PP_STRINGIZE(MAJOR_VER) BOOST_PP_STRINGIZE(MINOR_VER)

28
Me hace sonreír cómo la gente lanza Boost a todo.
Frerich Raabe

4
@Frerich: Llevando su argumento al extremo, la gente debería escribir sus propios compiladores primero en código de máquina en bruto, en lugar de lanzar g ++ en todo ... No tiene sentido reinventar la rueda. Los buenos programadores escriben código, los grandes reutilizan.
Maxim Egorushkin

@jonescb: simplemente abre el encabezado de impulso y compruébalo por ti mismo.
Maxim Egorushkin

10
Sí, lo intenté. Funcionó, pero usar un encabezado Boost en un programa C me parece un poco extraño.
jonescb

1
Oh, mi mal, no me di cuenta de la Cetiqueta.
Maxim Egorushkin
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.