wake-up-neo.com

Verkettung von C / C ++ - Makrozeichenfolgen

#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 args an eine andere Makrofunktion übergeben. Aber gibt es einen direkten Weg?

103
tvr

Wenn es sich um beide Saiten handelt, können Sie Folgendes tun:

#define STR3 STR1 STR2

Der Präprozessor verkettet benachbarte Zeichenfolgen automatisch.

EDIT:

Wie unten erwähnt, ist es nicht der Präprozessor, sondern der Compiler, der die Verkettung durchführt.

135
Sean

Für Zeichenfolgenliterale ist eine solche Lösung nicht erforderlich, da sie auf Sprachebene verkettet sind. Sie funktioniert ohnehin nicht, da "s" "1" kein gültiges Präprozessor-Token ist.

[Edit: Als Reaktion auf den falschen "Just for the record" -Kommentar darunter, der leider mehrere positive Stimmen erhalten hat, werde ich die obige Aussage wiederholen und feststellen, dass das Programmfragment

#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")

erzeugt diese Fehlermeldung aus der Vorverarbeitungsphase von gcc: Fehler: Das Einfügen von "" s "" und "" 1 "" ergibt kein gültiges Vorverarbeitungs-Token

]

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 erzeugen z. B. sowohl PPCAT_NX(s, 1) als auch PPCAT(s, 1) den Bezeichner s1, Sofern s nicht als Makro definiert ist. In diesem Fall PPCAT(s, 1) ergibt <macro value of s>1.

Weiter geht es mit den folgenden 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)"
97
Jim Balter

Hinweis: Das obige STRINGIZE -Makro ist cool, aber wenn Sie einen Fehler machen und sein Argument kein Makro ist - Sie hatten einen Tippfehler im Namen oder haben vergessen, #include Die Header-Datei - dann wird der Compiler den angeblichen Makronamen ohne Fehler in die Zeichenkette einfügen.

Wenn Sie beabsichtigen, dass das Argument für 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 wieder zu einer Zeichenfolge erweitern.

Es dauerte eine Weile, bis ich herausgefunden hatte, warum STRINGIZE(ENOENT) als "ENOENT" Statt "2" Endete ... Ich hatte errno.h Nicht eingeschlossen.

24
Jordan Brown