Verketten Sie int mit C Preprocessor mit String

90

Ich versuche herauszufinden, wie ich mit dem C- Präprozessor ein #define'd int mit einem #define' d-String verketten kann . Mein Compiler ist GCC 4.1 unter CentOS 5. Die Lösung sollte auch für MinGW funktionieren.

Ich möchte eine Versionsnummer an eine Zeichenfolge anhängen, aber die einzige Möglichkeit, sie zum Laufen zu bringen, besteht darin, eine Kopie der Versionsnummer zu erstellen, die als Zeichenfolgen definiert ist.

Das nächste, was ich finden konnte, war eine Methode zum Zitieren von Makroargumenten, aber es funktioniert nicht für #defines

Das funktioniert nicht.

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" #MAJOR_VER #MINOR_VER

Es funktioniert nicht ohne die #s entweder , weil die Werte Zahlen sind und es würde zu erweitern "/home/user/.myapp" 2 6, die nicht gültig ist C .

Das funktioniert, aber ich mag es nicht, Kopien der Versionsdefinitionen zu haben, weil ich sie auch als Zahlen brauche.

#define MAJOR_VER 2
#define MINOR_VER 6
#define MAJOR_VER_STR "2"
#define MINOR_VER_STR "6"
#define MY_FILE "/home/user/.myapp" MAJOR_VER_STRING MINOR_VER_STRING
jonescb
quelle
3
Mögliches Duplikat von Konvertieren eines Präprozessor-Tokens in eine Zeichenfolge
Ciro Santilli 5 冠状 病 六四 事件 5

Antworten:

167

Klassische C-Präprozessor-Frage ....

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" STR(MAJOR_VER) STR(MINOR_VER)

Durch die zusätzliche Indirektionsebene kann der Präprozessor die Makros erweitern, bevor sie in Zeichenfolgen konvertiert werden.

Lindydancer
quelle
3
STR () gibt in diesem Fall eine schmale Zeichenfolge. Gibt es eine Variante, um dies in eine breite Zeichenfolge umzuwandeln?
Gkns
4
Ich konnte nicht sagen, wie oft ich es gegoogelt und von dieser genauen Antwort kopiert habe, aber es wird zweistellig sein
MightyPork
Das erste "STR_HELPER" ist erforderlich, da '#' nur mit einem Makroargument funktioniert. Ich habe
einige Zeit gebraucht
@clarkttfu, irgendwie - ja, #funktioniert nur mit Makroargumenten . Das STR_HELPERMakro wird jedoch benötigt, um zu vermeiden, dass das Makro MAJOR_VERin eine Zeichenfolge umgewandelt wird "MAJOR_VAR", in der das Ergebnis angezeigt werden soll "2".
Lindydancer
12

Eine Arbeitsweise besteht darin, MY_FILE als parametrisches Makro zu schreiben:

#define MY_FILE(x,y) "/home..." #x #y

BEARBEITEN: Wie von "Lindydancer" festgestellt, erweitert diese Lösung keine Makros in Argumenten. Eine allgemeinere Lösung ist:

#define MY_FILE_(x,y) "/home..." #x #y
#define MY_FILE(x,y) MY_FILE_(x,y)
Giuseppe Guerrini
quelle
1
Meiner ehrlichen Meinung nach ist dies die beste Antwort und viel einfacher als die anderen Vorschläge. Ich bin überrascht, dass es keine bessere Bewertung bekommen hat!
Osirisgothra
5
Es ist eine saubere Lösung, die leider nicht funktioniert. Wenn das übergebene Argument MY_FILEMakros sind, z. B. Aund B, wird dieses Makro auf erweitert "/home..." "A" "B".
Lindydancer
2

Sie können dies mit BOOST_PP_STRINGIZE tun :

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" BOOST_PP_STRINGIZE(MAJOR_VER) BOOST_PP_STRINGIZE(MINOR_VER)
Maxim Egorushkin
quelle
28
Bringt mich zum Grinsen, wie Leute Boost auf alles werfen.
Frerich Raabe
4
@Frerich: Wenn Sie Ihre Argumentation auf die Spitze treiben, sollten die Leute ihre eigenen Compiler zuerst in rohen Maschinencode schreiben, anstatt g ++ auf alles zu werfen ... Es macht keinen Sinn, das Rad neu zu erfinden. Gute Programmierer schreiben Code, gute wiederverwenden.
Maxim Egorushkin
@jonescb: Öffnen Sie einfach den Boost-Header und überzeugen Sie sich selbst.
Maxim Egorushkin
10
Ja, ich habe es versucht. Es hat funktioniert, aber die Verwendung eines Boost-Headers in einem C-Programm erscheint mir seltsam.
Jonescb
1
Oh mein Gott, habe CTag nicht bemerkt .
Maxim Egorushkin