2011-03-28 11 views
57

Sto cercando di capire come posso concatenare una #define 'd int ad un #define' stringa d utilizzando il C preprocessore. Il mio compilatore è GCC 4.1 su CentOS 5. La soluzione dovrebbe funzionare anche per MinGW.Concatenate int a stringa utilizzando C preprocessore

Vorrei aggiungere un numero di versione a una stringa, ma l'unico modo in cui riesco a farlo funzionare è creare una copia del numero di versione definito come stringhe.

La cosa più vicina che ho trovato era un metodo di citare argomenti di macro, ma non funziona per #define s

Questo è non funziona.

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

Non funziona senza le # s sia perché i valori sono numeri e sarebbe espandono per "/home/user/.myapp" 2 6, che non è valido C.

Questo funziona, ma non mi piace avere copie della versione definite perché anch'io ne ho bisogno come numeri.

#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 
+3

Eventuali duplicati di [Converti un gettone preprocessore in una stringa] (http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string) –

risposta

97

classica domanda C preprocessore ....

#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) 

L'ulteriore livello di indirezione permetterà al preprocessore per espandere le macro prima sono convertiti in stringhe.

+2

Grazie. Funziona, ed è una soluzione molto pulita. – jonescb

+0

STR() in questo caso darà una stringa stretta. C'è una variazione per convertire questo in una stringa ampia? – gkns

2

È possibile farlo con BOOST_PP_STRINGIZE:

#define MAJOR_VER 2 
#define MINOR_VER 6 
#define MY_FILE "/home/user/.myapp" BOOST_PP_STRINGIZE(MAJOR_VER) BOOST_PP_STRINGIZE(MINOR_VER) 
+20

Mi fa sorridere come le persone lanciano Boost a tutto. –

+4

@Frerich: Considerando le tue argomentazioni estreme, le persone dovrebbero scrivere i propri compilatori prima nel codice macchina grezzo, piuttosto che lanciare g ++ a tutto ... Non c'è motivo di reinventare la ruota. I buoni programmatori scrivono il codice, i grandi ne riutilizzano. –

+0

@jonescb: basta aprire [l'intestazione di boost] (http://svn.boost.org/svn/boost/trunk/boost/preprocessor/stringize.hpp) e vedere di persona. –

8

Un modo di lavoro è scrivere my_file come macro parametrica:

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

EDIT: Come notato da "Lindydancer", questa soluzione non si espande macro in argomenti. Una soluzione più generale è:

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

Secondo la mia onesta opinione, questa è la risposta migliore, ed è molto più semplice degli altri suggerimenti. Sono sorpreso che non abbia ottenuto una valutazione migliore! – osirisgothra

+3

È una soluzione pulita che, sfortunatamente, non funziona. Se l'argomento passato a 'MY_FILE' sono macro, ad esempio' A' e 'B', questa macro si espanderà in' "/ home ..." "A" "B" '. – Lindydancer

+1

Corretto, ma esiste una soluzione ben nota (vedi modifica). –