#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
¿Es posible concatenar tiene STR3 == "s1"? Puede hacer esto pasando argumentos a otra función de macro. Pero, ¿existe una forma directa?
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
¿Es posible concatenar tiene STR3 == "s1"? Puede hacer esto pasando argumentos a otra función de macro. Pero, ¿existe una forma directa?
Respuestas:
Si son ambas cadenas, puede hacer:
#define STR3 STR1 STR2
El preprocesador concatena automáticamente cadenas adyacentes.
EDITAR:
Como se indica a continuación, no es el preprocesador sino el compilador el que realiza la concatenación.
L"a"
y "b"
obtener L"ab"
, pero puede concatenar L"a"
y L"b"
obtener L"ab"
.
No necesita ese tipo de solución para los literales de cadena, ya que están concatenados en el nivel del lenguaje y no funcionaría de todos modos porque "s" "1" no es un token de preprocesador válido.
[Editar: En respuesta al comentario incorrecto "Solo para el registro" a continuación que, lamentablemente, recibió varios votos a favor, reiteraré la declaración anterior y observaré que el fragmento del programa
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
produce este mensaje de error de la fase de preprocesamiento de gcc: error: pegar "" s "" y "" 1 "" no da un token de preprocesamiento válido
]
Sin embargo, para pegar tokens en general, intente esto:
/*
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define PPCAT_NX(A, B) A ## B
/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
*/
#define PPCAT(A, B) PPCAT_NX(A, B)
Entonces, por ejemplo, ambos PPCAT_NX(s, 1)
y PPCAT(s, 1)
producen el identificador s1
, a menos que s
se defina como una macro, en cuyo caso PPCAT(s, 1)
produce <macro value of s>1
.
Continuando con el tema están estas macros:
/*
* Turn A into a string literal without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define STRINGIZE_NX(A) #A
/*
* Turn A into a string literal after macro-expanding it.
*/
#define STRINGIZE(A) STRINGIZE_NX(A)
Luego,
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
Por el contrario,
STRINGIZE(PPCAT_NX(T1, T2)) // produces "T1T2"
STRINGIZE_NX(PPCAT_NX(T1, T2)) // produces "PPCAT_NX(T1, T2)"
#define T1T2 visit the zoo
STRINGIZE(PPCAT_NX(T1, T2)) // produces "visit the zoo"
STRINGIZE_NX(PPCAT(T1, T2)) // produces "PPCAT(T1, T2)"
"s""1"
es válido en C (y C ++). Son dos tokens (literales de cadena) que el compilador concatena y amenaza como un token.
"s""1" isn't a valid token
- eso es correcto; son, como dices, dos fichas. Pero agregarlos junto con ## los convertiría en un solo token de preprocesamiento, no dos tokens, por lo que el compilador no haría una concatenación, sino que el lexer los rechazaría (el lenguaje requiere un diagnóstico).
STRINGIZE_NX(whatever occurs here)
expande a "lo que ocurra aquí", independientemente de las definiciones de macro para lo que sea, ocurra o aquí.
if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"
que eso es falso y no se parece en nada a su prueba. Te estás esforzando por no entender o hacer esto bien, y no voy a responderte más.
Sugerencia: la STRINGIZE
macro anterior es genial, pero si comete un error y su argumento no es una macro, tuvo un error tipográfico en el nombre o se olvidó #include
del archivo de encabezado, entonces el compilador pondrá felizmente el nombre de la macro supuesta en el cadena sin error.
Si tiene la intención de que el argumento de STRINGIZE
sea siempre una macro con un valor C normal, entonces
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
lo expandirá una vez y verificará su validez, lo descartará y luego lo expandirá nuevamente en una cadena.
Me tomó un tiempo descubrir por qué STRINGIZE(ENOENT)
terminaba como en "ENOENT"
lugar de "2"
... no había incluidoerrno.h
.
,
operador. :)
((1),"1") "." ((2),"2")
lugar de solo "1" "." "2")
STRINGIZE
definición original , "The value of ENOENT is " STRINGIZE(ENOENT)
funciona, mientras que "The value of ENOENT is" STRINGIZE_EXPR(X)
produce un error.