Łączenie ciągów makr C/C ++


#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2

Czy można połączyć STR3 == "s1"?
Możesz to zrobić, przekazując argumenty do innej funkcji makra. Ale czy istnieje bezpośrednia ścieżka?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli są to oba ciągi, możesz po prostu zrobić:
#define STR3 STR1 STR2

Preprocesor automatycznie łączy sąsiednie wiersze.

EDIT

:
Jak zauważono poniżej, to nie preprocesor, ale kompilator wykonuje konkatenację.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Nie potrzebujesz tego rodzaju rozwiązania dla literałów łańcuchowych, ponieważ są one konkatenowane na poziomie języka i nadal nie będą działać, ponieważ „s” „1” nie jest prawidłowym tokenem preprocesora.
[Edycja: w odpowiedzi na poniższy niepoprawny komentarz „Just for the record”, który niestety otrzymał wiele głosów za, powtórzę powyższe stwierdzenie i zauważę, że fragment programu
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")

wyrzuca ten komunikat o błędzie z fazy wstępnego przetwarzania gcc:

błąd: wstawienie „„ s ”” i „„ 1 ”” nie daje prawidłowego tokena

wstępne przetwarzanie ]
Jednak w przypadku ogólnego wstawiania tokena spróbuj wykonać następujące czynności:
/*
* 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)

Następnie, na przykład, zarówno
PPCAT_NX (s, 1)
, jak i
PPCAT (s, 1)
tworzą identyfikator
s1
, jeśli tylko
s
nie jest zdefiniowane jako makro, w którym to przypadku
PPCAT (s, 1)
generuje
<wartość &="" 1="" <="" code="" >="" makra="" s="">. 
</wartość>
Kontynuując temat, są następujące makra:
/*
* 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)

Następnie,
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2))// produces "s1"

Natomiast
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)"
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Wskazówka: powyższe makro
STRINGIZE
jest fajne, ale jeśli popełnisz błąd i jego argument nie jest makrem - masz literówkę w nazwie lub zapomniałeś
#include
w plik nagłówkowy - wtedy kompilator szczęśliwie umieści sugerowaną nazwę makra w ciągu znaków bez błędu.
Jeśli przyjmiesz, że argument
STRINGIZE
jest zawsze makrem z normalną wartością C, to
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))

rozwinie go raz i sprawdzi poprawność, odrzuci to, a następnie ponownie rozwinie do łańcucha.
Zajęło mi trochę czasu, zanim zrozumiałem, dlaczego
STRINGIZE (ENOENT)
skończyło się na
„ENOENT”
zamiast
„2”
... Nie 'nie zawiera
errno.h
.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się