#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Ist es möglich, STR3 == "s1" zu verketten? Sie können dies tun, indem Sie Argumente an eine andere Makrofunktion übergeben. Aber gibt es einen direkten Weg?
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Ist es möglich, STR3 == "s1" zu verketten? Sie können dies tun, indem Sie Argumente an eine andere Makrofunktion übergeben. Aber gibt es einen direkten Weg?
Antworten:
Wenn beide Zeichenfolgen sind, können Sie einfach Folgendes tun:
#define STR3 STR1 STR2
Der Präprozessor verkettet automatisch benachbarte Zeichenfolgen.
BEARBEITEN:
Wie unten erwähnt, ist es nicht der Präprozessor, sondern der Compiler, der die Verkettung vornimmt.
L"a"
und "b"
bekommen L"ab"
, aber man kann verketten L"a"
und L"b"
bekommen L"ab"
.
Sie benötigen diese Art von Lösung für Zeichenfolgenliterale nicht, da sie auf Sprachebene verkettet sind und es sowieso nicht funktionieren würde, da "s" "1" kein gültiges Präprozessor-Token ist.
[Bearbeiten: Als Antwort auf den falschen Kommentar "Nur für den Datensatz" unten, der leider mehrere positive Stimmen erhalten hat, werde ich die obige Aussage wiederholen und feststellen, dass das Programm fragmentiert ist
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
erzeugt diese Fehlermeldung aus der Vorverarbeitungsphase von gcc: error: Das Einfügen von "" s "" und "" 1 "" ergibt kein gültiges Vorverarbeitungstoken
]]
Versuchen Sie jedoch für das allgemeine Einfügen von Token Folgendes:
/*
* 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)
Dann zB beide PPCAT_NX(s, 1)
und PPCAT(s, 1)
erzeugen den Bezeichner s1
, sofern nicht s
als Makro definiert, in welchem Fall PPCAT(s, 1)
erzeugt wird <macro value of s>1
.
Weiter zum Thema sind diese Makros:
/*
* 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)
Dann,
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
Im Gegensatz,
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"
ist in C (und C ++) gültig. Dies sind zwei Token (String-Literale), die der Compiler selbst zusammenfassen und als ein Token bedrohen würde.
"s""1" isn't a valid token
- das ist richtig; Es sind, wie Sie sagen, zwei Token. Wenn Sie sie jedoch zusammen mit ## anheften, werden sie zu einem einzigen Vorverarbeitungstoken, nicht zu zwei Token, und der Compiler führt keine Verkettung durch, sondern der Lexer lehnt sie ab (die Sprache erfordert eine Diagnose).
STRINGIZE_NX(whatever occurs here)
sich also zu "was auch immer hier vorkommt", unabhängig von Makrodefinitionen für was auch immer, vorkommt oder hier.
if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"
- das ist falsch und nichts mit Ihrem Test zu tun. Sie bemühen sich, dies nicht zu verstehen oder richtig zu machen, und ich werde Ihnen nicht weiter antworten.
Hinweis: Das STRINGIZE
obige Makro ist cool, aber wenn Sie einen Fehler machen und sein Argument kein Makro ist - Sie hatten einen Tippfehler im Namen oder haben #include
die Header-Datei vergessen -, fügt der Compiler den angeblichen Makronamen gerne in das ein Zeichenfolge ohne Fehler.
Wenn Sie beabsichtigen, dass das Argument to STRINGIZE
immer ein Makro mit einem normalen C-Wert ist, dann
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
wird es einmal erweitern und auf Gültigkeit prüfen, verwerfen und dann erneut zu einer Zeichenfolge erweitern.
Es dauerte eine Weile, um herauszufinden , warum STRINGIZE(ENOENT)
wurde enden wie "ENOENT"
statt "2"
... Ich hatte nicht im Preis enthalten errno.h
.
,
Bedieners. :)
((1),"1") "." ((2),"2")
statt nur "1". "" 2 "führt)
STRINGIZE
Definition "The value of ENOENT is " STRINGIZE(ENOENT)
funktioniert, während "The value of ENOENT is" STRINGIZE_EXPR(X)
ein Fehler erzeugt.