다른 매크로에 전달된 인수에 대해 작동하는 매크로를 어떻게 정의할 수 있습니까? 특히 다음을 고려하십시오.
#define PRINT(a) printf(#a": %d", a) #define PRINT_ALL(...) ? ? ? THE PROBLEM ? ? ?
원하는 사용법:
int a = 1, b = 3, d = 0; PRINT_ALL(a,b,d);
재귀 매크로는 색다른 해결 방법을 사용하여 C에서 가능합니다. 목표는 다음과 유사한 MAP 매크로를 생성하는 것입니다.
#define PRINT(a) printf(#a": %d", a) MAP(PRINT, a, b, c) /* Apply PRINT to a, b, and c */
평가되지 않는 매크로 호출과 유사한 것을 출력하는 방법을 만드는 것부터 시작합니다.
#define MAP_OUT
다음 매크로를 고려하세요.
#define A(x) x B MAP_OUT (x) #define B(x) x A MAP_OUT (x)
A(blah)를 평가하면 텍스트가 생성됩니다.
blah B (blah)
전처리기는 여기서 재귀를 감지하지 않습니다. (ㅋㅋㅋ) 현 단계에서는 전화가 문자일 뿐이에요. 이 텍스트를 전처리기에 다시 공급하면 확장됩니다.
blah blah A (blah)
이 출력을 다시 평가하면 A(어쩌고) 매크로가 확장되어 재귀가 완료됩니다. 이 프로세스는 출력이 다시 전처리기에 다시 공급될 때까지 계속됩니다.
여러 평가를 용이하게 하기 위해 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__)))
각각 레벨은 이전 버전의 노력을 증폭시켜 궁극적으로 입력을 365회 평가합니다. 예를 들어 EVAL(A(blah))은 blah의 365개 복사본과 평가되지 않은 B(blah)가 뒤따르는 결과를 생성합니다. 이 설정은 특정 스택 깊이 제한 내에서 재귀에 대한 기본 사항을 제공합니다.
다음 장애물은 재귀를 종료할 시기를 결정하는 것입니다.
MAP_END 매크로를 다음과 같이 정의합니다. 목록 끝 표시:
#define MAP_END(...)
이 매크로를 평가하면 재귀의 끝을 알리는 신호로 아무 작업도 수행되지 않습니다.
두 매크로 중에서 선택하려면 목록을 비교하는 MAP_NEXT를 사용합니다. 특수 목록 끝 표시()가 있는 항목:
#define MAP_GET_END() 0, MAP_END #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__)
이 매크로는 현재 목록 항목 x에 연산 f를 적용한 후 다음 목록 항목인 peek를 검사하여 계속할지 여부를 결정합니다.
마지막으로 최상위 MAP 매크로의 모든 것을 어셈블합니다.
#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))
이 매크로는 목록 끝에 () 표시를 추가하고 EVAL을 통해 전체를 전달하여 결과를 반환합니다.
코드는 GitHub에서 라이브러리로 제공됩니다. 편리하게 이용하세요.
위 내용은 C의 다른 매크로에 전달된 인수에 대해 작동하는 매크로를 정의하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!