#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
É possível concatenar ter STR3 == "s1"? Você pode fazer isso passando args para outra função Macro. Mas existe um caminho direto?
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
É possível concatenar ter STR3 == "s1"? Você pode fazer isso passando args para outra função Macro. Mas existe um caminho direto?
Respostas:
Se forem as duas strings, você pode fazer:
#define STR3 STR1 STR2
O pré-processador concatena automaticamente as seqüências adjacentes.
EDITAR:
Como observado abaixo, não é o pré-processador, mas o compilador que faz a concatenação.
L"a"
e "b"
obter L"ab"
, mas pode concatenar L"a"
e L"b"
obter L"ab"
.
Você não precisa desse tipo de solução para literais de cadeias, pois elas são concatenadas no nível do idioma e, de qualquer maneira, não funcionariam porque "s" "1" não é um token de pré-processador válido.
[Editar: Em resposta ao comentário incorreto "Just for the record" abaixo, que infelizmente recebeu vários upvotes, reiterarei a declaração acima e observarei que o fragmento do programa
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
produz essa mensagem de erro da fase de pré-processamento do gcc: error: colar "" s "" e "" 1 "" não fornece um token de pré-processamento válido
]
No entanto, para colar o token geral, tente o seguinte:
/*
* 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)
Então, por exemplo, ambos PPCAT_NX(s, 1)
e PPCAT(s, 1)
produza o identificador s1
, a menos que s
seja definido como uma macro, caso em que PPCAT(s, 1)
produz <macro value of s>1
.
Continuando com o tema estão 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)
Então,
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
Por contraste,
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"
é válido em C (e C ++). São dois tokens (strings literais) que o compilador concatena a si próprio e ameaça como um token.
"s""1" isn't a valid token
- isso está correto; são, como você diz, dois tokens. Mas juntá-los com ## os tornaria um único token de pré-processamento, não dois tokens; portanto, o compilador não faria uma concatenação, e o lexer os rejeitaria (a linguagem requer um diagnóstico).
STRINGIZE_NX(whatever occurs here)
expande para "o que quer que ocorra aqui", independentemente de quaisquer definições de macro para o que quer que ocorra, ou aqui.
if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"
- isso é falso e não é nada parecido com o seu teste. Você está se esforçando para não entender ou entender direito, e eu não vou responder mais a você.
Dica: A STRINGIZE
macro acima é legal, mas se você cometer um erro e seu argumento não for uma macro - você digitou um erro de digitação no nome ou esqueceu #include
o arquivo de cabeçalho -, o compilador colocará o nome da macro no campo string sem erro.
Se você pretende que o argumento to STRINGIZE
seja sempre uma macro com um valor C normal,
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
irá expandi-lo uma vez e verificar sua validade, descarte-o e depois expanda-o novamente em uma sequência.
Levei um tempo para descobrir por que STRINGIZE(ENOENT)
estava acabando, em "ENOENT"
vez de "2"
... eu não tinha incluído errno.h
.
,
operador. :)
((1),"1") "." ((2),"2")
vez de apenas "1" "." "2")
STRINGIZE
definição original , "The value of ENOENT is " STRINGIZE(ENOENT)
funciona, enquanto "The value of ENOENT is" STRINGIZE_EXPR(X)
produz um erro.