#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Est-il possible de concaténer ont STR3 == "s1"? Vous pouvez le faire en passant des arguments à une autre fonction Macro. Mais y a-t-il un moyen direct?
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Est-il possible de concaténer ont STR3 == "s1"? Vous pouvez le faire en passant des arguments à une autre fonction Macro. Mais y a-t-il un moyen direct?
Réponses:
Si ce sont les deux chaînes, vous pouvez simplement faire:
#define STR3 STR1 STR2
Le préprocesseur concatène automatiquement les chaînes adjacentes.
ÉDITER:
Comme indiqué ci-dessous, ce n'est pas le préprocesseur mais le compilateur qui effectue la concaténation.
L"a"
et "b"
obtenir L"ab"
, mais vous pouvez concaténer L"a"
et L"b"
obtenir L"ab"
.
Vous n'avez pas besoin de ce genre de solution pour les chaînes littérales, puisqu'elles sont concaténées au niveau de la langue, et cela ne fonctionnerait pas de toute façon parce que "s" "1" n'est pas un jeton de préprocesseur valide.
[Edit: En réponse au commentaire incorrect "Juste pour mémoire" ci-dessous qui a malheureusement reçu plusieurs votes positifs, je vais réitérer la déclaration ci-dessus et observer que le fragment de programme
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
produit ce message d'erreur à partir de la phase de prétraitement de gcc: error: coller "" s "" et "" 1 "" ne donne pas un jeton de prétraitement valide
]
Cependant, pour le collage général de jetons, essayez ceci:
/*
* 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)
Ensuite, par exemple, les deux PPCAT_NX(s, 1)
et PPCAT(s, 1)
produisent l'identifiant s1
, sauf s'il s
est défini comme une macro, auquel cas PPCAT(s, 1)
produit <macro value of s>1
.
Continuant sur le thème sont ces 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)
Ensuite,
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
Par contre,
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"
est valide en C (et C ++). Ce sont deux jetons (littéraux de chaîne) que le compilateur concatre et menace comme un seul jeton.
"s""1" isn't a valid token
- c'est exact; il s'agit, comme vous le dites, de deux jetons. Mais les assembler avec ## en ferait un seul jeton de prétraitement, pas deux jetons, et ainsi le compilateur ne ferait pas de concaténation, mais plutôt le lexeur les rejetterait (le langage nécessite un diagnostic).
STRINGIZE_NX(whatever occurs here)
S'étend donc à "tout ce qui se passe ici", quelles que soient les définitions de macro pour ce qui se passe ou ici.
if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"
- c'est faux et cela n'a rien à voir avec votre test. Vous vous efforcez de ne pas comprendre ou de ne pas comprendre cela correctement, et je ne vais pas vous répondre davantage.
Astuce: La STRINGIZE
macro ci-dessus est cool, mais si vous faites une erreur et que son argument n'est pas une macro - vous avez eu une faute de frappe dans le nom, ou vous avez oublié #include
le fichier d'en-tête - alors le compilateur mettra volontiers le nom de la macro dans le chaîne sans erreur.
Si vous souhaitez que l'argument de STRINGIZE
soit toujours une macro avec une valeur C normale, alors
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
le développera une fois et vérifiera sa validité, le rejettera, puis le développera à nouveau en une chaîne.
Il m'a fallu un certain temps pour comprendre pourquoi STRINGIZE(ENOENT)
finissait comme "ENOENT"
au lieu de "2"
... je n'avais pas inclus errno.h
.
,
opérateur. :)
((1),"1") "." ((2),"2")
au lieu de seulement "1" "." "2")
STRINGIZE
définition originale , "The value of ENOENT is " STRINGIZE(ENOENT)
fonctionne, alors que "The value of ENOENT is" STRINGIZE_EXPR(X)
produit une erreur.