Heim  >  Artikel  >  Backend-Entwicklung  >  Wie können Sie trotz der Einschränkungen der Makroerweiterung eine rekursive Makrofunktionalität in C erreichen?

Wie können Sie trotz der Einschränkungen der Makroerweiterung eine rekursive Makrofunktionalität in C erreichen?

Barbara Streisand
Barbara StreisandOriginal
2024-11-16 02:17:03237Durchsuche

How can you achieve recursive macro functionality in C, despite the limitations of macro expansion?

Rekursive Makros in C mit Argumentmakros

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.

Grundprinzipien

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.

Rekursive Auswertung

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.

Rekursionsbeendigung

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)
MAP_NEXT vergleicht das aktuelle Element mit der End-of-List-Markierung (). Es gibt MAP_END zurück, wenn sie übereinstimmen, oder andernfalls den nächsten Parameter.

Praktische Implementierung

Durch die Kombination dieser Elemente können wir praktische Versionen der A- und B-Makros erstellen:

#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__)
MAP0 und MAP1 wenden die Operation f auf das aktuelle Element x an. Anschließend überprüfen sie das nächste Element, Peek, um zu bestimmen, ob die Rekursion fortgesetzt oder beendet werden soll.

Schließlich verknüpfen wir alles mit dem MAP-Makro der obersten Ebene:

#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))
MAP-Orte eine End-of-List-Markierung auf der Argumentliste und leitet sie durch EVAL.

Durch die Verwendung dieser Techniken können Sie rekursive Makrofunktionalität in C erreichen und so komplexe Makrobasierte Verarbeitung.

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn