In der C-Programmierung ist es nicht einfach, Makros rekursiv auf Makroargumente anzuwenden. Mit einer komplexen Problemumgehung ist es jedoch möglich, ein MAP-Makro mit der gewünschten Funktionalität zu erreichen.
Um die Rekursion zu initiieren, definieren wir ein MAP_OUT-Makro, das als Platzhalter für dient Makroerweiterung:
#define MAP_OUT
Als nächstes erstellen wir zur Demonstration zwei Makros, A und B Rekursion:
#define A(x) x B MAP_OUT (x) #define B(x) x A MAP_OUT (x)
Die Auswertung von A(blah) führt zur folgenden Ausgabe:
blah B (blah)
Der Präprozessor behandelt B(blah) als Klartext, da es sich noch nicht um einen Makroaufruf handelt. Wenn dieser Text erneut verarbeitet wird, wird er erweitert, um Folgendes zu erzeugen:
blah blah A (blah)
Durch die kontinuierliche Rückführung der Ausgabe in den Präprozessor können wir die Rekursion auf unbestimmte Zeit aufrechterhalten.
Um diese wiederholte Auswertung zu automatisieren, verwenden wir das EVAL-Makro:
#define EVAL0(...) __VA_ARGS__ #define EVAL1(...) EVAL0 (EVAL0 (EVAL0 (__VA_ARGS__))) #define EVAL2(...) EVAL1 (EVAL1 (EVAL1 (__VA_ARGS__))) #define EVAL3(...) EVAL2 (EVAL2 (EVAL2 (__VA_ARGS__))) #define EVAL4(...) EVAL3 (EVAL3 (EVAL3 (__VA_ARGS__))) #define EVAL(...) EVAL4 (EVAL4 (EVAL4 (__VA_ARGS__)))
Das EVAL-Makro propagiert seine Argumente durch einen Baum von Makroaufrufen und multipliziert deren Auswertungsanzahl mit 365.
Um eine endlose Rekursion zu verhindern, benötigen wir einen Mechanismus zur Beendigung. Wir definieren ein spezielles Makro mit dem Namen MAP_END:
#define MAP_END(...)
Bei der Auswertung führt dieses Makro nichts aus und stoppt effektiv die Rekursion.
Um zwischen rekursiven und terminierenden Makros zu wählen, führen wir MAP_NEXT:
#define MAP_NEXT0(item, next, ...) next MAP_OUT #define MAP_NEXT1(item, next) MAP_NEXT0 (item, next, 0) #define MAP_NEXT(item, next) MAP_NEXT1 (MAP_GET_END item, next)
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__) #define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)
#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))
Das obige ist der detaillierte Inhalt vonWie können Sie trotz der Einschränkungen der Makroerweiterung eine rekursive Makrofunktionalität in C erreichen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!