> 백엔드 개발 > C++ > C의 다른 매크로에 전달된 인수에 대해 작동하는 매크로를 정의하는 방법은 무엇입니까?

C의 다른 매크로에 전달된 인수에 대해 작동하는 매크로를 정의하는 방법은 무엇입니까?

Linda Hamilton
풀어 주다: 2024-11-15 15:02:03
원래의
653명이 탐색했습니다.

How to Define a Macro That Operates on Arguments Passed to Another Macro in C?

매크로 인수 내의 매크로

문제

다른 매크로에 전달된 인수에 대해 작동하는 매크로를 어떻게 정의할 수 있습니까? 특히 다음을 고려하십시오.

#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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿