#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 sseja 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 STRINGIZEmacro 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 #includeo arquivo de cabeçalho -, o compilador colocará o nome da macro no campo string sem erro.
Se você pretende que o argumento to STRINGIZEseja 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")
STRINGIZEdefinição original , "The value of ENOENT is " STRINGIZE(ENOENT)funciona, enquanto "The value of ENOENT is" STRINGIZE_EXPR(X)produz um erro.