C 프로그래밍에서는 매크로 인수에 매크로를 재귀적으로 적용하는 것이 간단하지 않습니다. 그러나 복잡한 해결 방법을 사용하면 원하는 기능을 갖춘 MAP 매크로를 얻을 수 있습니다.
재귀를 시작하기 위해 자리 표시자 역할을 하는 MAP_OUT 매크로를 정의합니다. 매크로 확장:
#define MAP_OUT
다음으로 재귀를 보여주기 위해 두 개의 매크로 A와 B를 만듭니다.
#define A(x) x B MAP_OUT (x) #define B(x) x A MAP_OUT (x)
A(blah)를 평가하면 다음과 같은 결과가 나옵니다.
blah B (blah)
전처리기는 B(blah)가 아직 매크로 호출이 아니기 때문에 일반 텍스트로 처리합니다. 이 텍스트가 재처리되면 확장되어 다음을 생성합니다.
blah blah A (blah)
출력을 계속해서 전처리기에 다시 공급함으로써 재귀를 무기한 유지할 수 있습니다.
이 반복 평가를 자동화하기 위해 EVAL 매크로를 사용합니다.
#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__)))
EVAL 매크로는 평가 횟수에 365를 곱하여 매크로 호출 트리를 통해 인수를 전파합니다.
무한 재귀를 방지하려면 종료 메커니즘이 필요합니다. MAP_END라는 특수 매크로를 정의합니다.
#define MAP_END(...)
평가 시 이 매크로는 아무 작업도 하지 않고 효과적으로 재귀를 중지합니다.
재귀 매크로와 종료 매크로 중에서 선택하려면 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는 현재 항목을 목록 끝 표시()와 비교합니다. 일치하면 MAP_END를 반환하고, 그렇지 않으면 다음 매개변수를 반환합니다.
이러한 요소를 결합하면 A 및 B 매크로의 실용적인 버전을 만들 수 있습니다.
#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 및 MAP1은 현재 항목 x에 연산 f를 적용합니다. 그런 다음 다음 항목인 peek를 확인하여 재귀를 계속할지 아니면 종료할지 결정합니다.
마지막으로 모든 것을 최상위 MAP 매크로로 연결합니다.
#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))
MAP 장소 인수 목록에 목록 끝 표시를 추가하고 이를 EVAL을 통해 전달합니다.
이러한 기술을 활용하면 C에서 재귀 매크로 기능을 구현하여 복잡한 매크로 기반 처리가 가능해집니다.
위 내용은 매크로 확장의 한계에도 불구하고 C에서 재귀 매크로 기능을 어떻게 달성할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!