W poniższym kodzie, co robi ##
?Co oznacza podwójny skrót (#) w makrze?
#define MAKE_TYPE(myname) \
typedef int myname ## Id; \
W poniższym kodzie, co robi ##
?Co oznacza podwójny skrót (#) w makrze?
#define MAKE_TYPE(myname) \
typedef int myname ## Id; \
##
w makro jest konkatenacją. Tutaj MAKE_TYPE(test)
rozszerzy się do: typedef int testId
.
Od 16.3.3 (Operator ##):
Dla obu obiektowy jak i funkcja makro podobnych inwokacji, zanim lista wymiana jest ponownie zbadana dla więcej nazw makr do zastąpienia, każdy instancji ## przerób tokena liście zastępczej (nie z argument) zostaje usunięte, a poprzedzającym wyprzedzającego znacznik jest łączone z następujących przerób tokena
że chciałby podkreślić * przed lista wymiany jest ponownie sprawdzana *. Jeśli napiszesz 'MAKE_TYPE (OBJECT (Foo))' będziesz miał 'typedef int OBJECT (Foo) Id;' ... który jest oczywiście nieważny. Radzenie sobie z makrami jest ... skomplikowane, a najlepiej unikane, szczególnie w tak trywialnych przypadkach, w których tylko zaciemniają rzeczy. –
icecrime jest poprawny, ale ważne jest, aby podkreślić, że tokeny muszą być ważnymi tokeny preprocessingu. Przykłady:
#define CONCAT(a,b) a ## b
CONCAT(ClassyClass, <int>); // bad, <int> is not a valid preprocessing token
CONCAT(Symbol, __LINE__); // valid as both are valid tokens
To spowodowało wiele frustracji kilka lat temu, ponieważ chciałem połączyć trzy rzeczy razem, a kombinacja ani pierwszej, ani ostatniej pary nie była poprawnymi żetonami preprocesingu. –
Świetny punkt, ale nie odpowiedź. Powinien być komentarzem do icecrime. –
zasadzie kopią [SO 1489932 preprocesora C i konkatenacji] (http://stackoverflow.com/questions/1489932/c-preprocessor-and-concatenation/) –