#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
È possibile concatenare have STR3 == "s1"? Puoi farlo passando gli argomenti a un'altra funzione Macro. Ma esiste un modo diretto?
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
È possibile concatenare have STR3 == "s1"? Puoi farlo passando gli argomenti a un'altra funzione Macro. Ma esiste un modo diretto?
Risposte:
Se sono entrambe le stringhe puoi semplicemente fare:
#define STR3 STR1 STR2
Il preprocessore concatena automaticamente le stringhe adiacenti.
MODIFICARE:
Come indicato di seguito, non è il preprocessore ma il compilatore che esegue la concatenazione.
L"a"e "b"ottenere L"ab", ma puoi concatenare L"a"e L"b"ottenere L"ab".
Non hai bisogno di quel tipo di soluzione per i letterali stringa, poiché sono concatenati a livello di linguaggio, e non funzionerebbe comunque perché "s" "1" non è un token preprocessore valido.
[Modifica: in risposta al commento "Solo per la cronaca" errato di seguito che purtroppo ha ricevuto diversi voti positivi, ribadirò l'affermazione sopra e osserverò che il frammento di programma
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
produce questo messaggio di errore dalla fase di pre-elaborazione di gcc: errore: incollare "" s "" e "" 1 "" non fornisce un token di pre-elaborazione valido
]
Tuttavia, per incollare token generali, prova questo:
/*
* 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)
Quindi, ad esempio, entrambi PPCAT_NX(s, 1)e PPCAT(s, 1)producono l'identificatore s1, a meno che non ssia definito come macro, nel qual caso PPCAT(s, 1)produce <macro value of s>1.
Continuando sul tema ci sono queste macro:
/*
* 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)
Poi,
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
Al contrario,
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"è valido in C (e C ++). Sono due token (stringhe letterali) che il compilatore potrebbe concatenare e minacciare come un unico token.
"s""1" isn't a valid token- è corretto; sono, come dici tu, due gettoni. Ma unirli insieme a ## li renderebbe un unico token di pre-elaborazione, non due token, e quindi il compilatore non farebbe una concatenazione, piuttosto il lexer li rifiuterebbe (il linguaggio richiede una diagnostica).
STRINGIZE_NX(whatever occurs here)espande a "qualunque cosa accada qui", indipendentemente da qualsiasi definizione di macro per qualunque cosa, accada o qui.
if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"che è falso e non ha niente a che fare con il tuo test. Stai cercando di non capire o di non farlo bene, e non ti risponderò ulteriormente.
Suggerimento: la STRINGIZEmacro sopra è interessante, ma se commetti un errore e il suo argomento non è una macro - hai avuto un errore di battitura nel nome o hai dimenticato #includeil file di intestazione - allora il compilatore metterà felicemente il nome della macro presunta nel stringa senza errori.
Se intendi che l'argomento a STRINGIZEsia sempre una macro con un valore C normale, allora
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
lo espanderà una volta e ne verificherà la validità, lo scarterà e poi lo espanderà di nuovo in una stringa.
Mi ci è voluto un po 'per capire perché STRINGIZE(ENOENT)stava finendo come "ENOENT"invece di "2"... non avevo incluso errno.h.
,dell'operatore. :)
((1),"1") "." ((2),"2")invece di "1" "." "2")
STRINGIZEdefinizione originale , "The value of ENOENT is " STRINGIZE(ENOENT)funziona, mentre "The value of ENOENT is" STRINGIZE_EXPR(X)produce un errore.