Home > Backend Development > C++ > How can you achieve recursive macro functionality in C, despite the limitations of macro expansion?

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

Barbara Streisand
Release: 2024-11-16 02:17:03
Original
329 people have browsed it

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

Recursive Macros in C Using Argument Macros

In C programming, it is not straightforward to apply macros recursively to macro arguments. However, employing a complex workaround, it is possible to achieve a MAP macro with the desired functionality.

Core Principles

To initiate the recursion, we define a MAP_OUT macro that serves as a placeholder for macro expansion:

#define MAP_OUT
Copy after login

Next, we create two macros, A and B, to demonstrate recursion:

#define A(x) x B MAP_OUT (x)
#define B(x) x A MAP_OUT (x)
Copy after login

Evaluating A(blah) results in the following output:

blah B (blah)
Copy after login

The preprocessor treats B(blah) as plain text since it is not yet a macro call. When this text is reprocessed, it expands to produce:

blah blah A (blah)
Copy after login

By continuously feeding the output back into the preprocessor, we can sustain the recursion indefinitely.

Recursive Evaluation

To automate this repeated evaluation, we use the EVAL macro:

#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__)))
Copy after login

The EVAL macro propagates its arguments through a tree of macro calls, multiplying their evaluation count by 365.

Recursion Termination

To prevent endless recursion, we need a mechanism for termination. We define a special macro named MAP_END:

#define MAP_END(...)
Copy after login

When evaluated, this macro does nothing, effectively stopping the recursion.

To select between recursive and terminating macros, we introduce 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)
Copy after login

MAP_NEXT compares the current item with the end-of-list marker (). It returns MAP_END if they match, or the next parameter otherwise.

Practical Implementation

Combining these elements, we can create practical versions of the A and B macros:

#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__)
Copy after login

MAP0 and MAP1 apply the operation f to the current item x. They then check the next item, peek, to determine whether to continue or end the recursion.

Finally, we tie everything together with the top-level MAP macro:

#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))
Copy after login

MAP places an end-of-list marker on the argument list and passes it through EVAL.

By utilizing these techniques, you can achieve recursive macro functionality in C, enabling complex macro-based processing.

The above is the detailed content of How can you achieve recursive macro functionality in C, despite the limitations of macro expansion?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template