#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Czy można łączyć, że STR3 == "s1"? Możesz to zrobić, przekazując argumenty do innej funkcji Macro. Ale czy istnieje bezpośredni sposób?
c++
c
c-preprocessor
tvr
źródło
źródło
Odpowiedzi:
Jeśli to oba ciągi, możesz po prostu zrobić:
Preprocesor automatycznie łączy sąsiednie ciągi.
EDYTOWAĆ:
Jak zauważono poniżej, to nie preprocesor, ale kompilator wykonuje konkatenację.
źródło
L"a"
i"b"
dostaćL"ab"
, ale można złączyćL"a"
iL"b"
dostaćL"ab"
.Nie potrzebujesz tego rodzaju rozwiązania dla literałów łańcuchowych, ponieważ są one konkatenowane na poziomie języka, a i tak by nie zadziałało, ponieważ „s” „1” nie jest prawidłowym tokenem preprocesora.
[Edytuj: W odpowiedzi na niepoprawny komentarz "Tylko do zapisu" poniżej, który niestety otrzymał kilka głosów za, powtórzę powyższe stwierdzenie i zauważę, że fragment programu
generuje ten komunikat o błędzie z fazy przetwarzania wstępnego gcc: błąd: wklejanie "" s "" i "1" "nie daje prawidłowego tokena przetwarzania wstępnego
]
Jednak w przypadku ogólnego wklejania tokenów spróbuj tego:
Następnie, na przykład, oba
PPCAT_NX(s, 1)
iPPCAT(s, 1)
produkują identyfikators1
, chyba żes
jest zdefiniowane jako makro, w którym to przypadkuPPCAT(s, 1)
produkuje<macro value of s>1
.Kontynuacją tematu są te makra:
Następnie,
Natomiast
źródło
"s""1"
obowiązuje w C (i C ++). Są to dwa tokeny (literały ciągów), które kompilator połączy ze sobą i zagrozi jako jeden token."s""1" isn't a valid token
- to jest poprawne; są to, jak mówisz, dwa żetony. Ale połączenie ich razem z ## uczyniłoby je pojedynczym tokenem przetwarzania wstępnego, a nie dwoma, więc kompilator nie wykonałby konkatenacji, a lekser odrzuciłby je (język wymaga diagnostyki).STRINGIZE_NX(whatever occurs here)
Rozwija się więc do „cokolwiek tu się dzieje”, niezależnie od jakichkolwiek makdefinicji tego, co się dzieje, lub tutaj.if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"
- to nieprawda i w niczym nie przypomina twojego testu. Bardzo starasz się nie zrozumieć lub nie zrobić tego dobrze, i nie zamierzam ci dalej odpowiadać.Wskazówka:
STRINGIZE
powyższe makro jest fajne, ale jeśli popełnisz błąd i jego argument nie jest makrem - miałeś literówkę w nazwie lub zapomniałeś#include
pliku nagłówkowego - kompilator szczęśliwie umieści rzekomą nazwę makra w ciąg bez błędu.Jeśli zamierzasz, aby argumentem
STRINGIZE
zawsze było makro z normalną wartością C, torozwinie go raz i sprawdzi, czy jest poprawny, odrzuci to, a następnie ponownie przekształci w łańcuch.
Zajęło mi trochę czasu, zanim zrozumiałem , dlaczego
STRINGIZE(ENOENT)
skończyło się na tym, że"ENOENT"
zamiast"2"
… nie uwzględniłemerrno.h
.źródło
,
operatora. :)((1),"1") "." ((2),"2")
zamiast „1” ”.„ „2”)STRINGIZE
definicją"The value of ENOENT is " STRINGIZE(ENOENT)
działa, podczas gdy"The value of ENOENT is" STRINGIZE_EXPR(X)
powoduje błąd.