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

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.


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)

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)

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.