2009-11-20 8 views
2

나는 개념적으로 이와 비슷한 것을하려고 노력하고있다. 그러나 어떤 아이디어로도 작동하지 못하는 것처럼 보인다.C 프로그래밍 : 토큰 같은 매크로 전 처리기

#include <stdio.h> 

int main(int argc , char const *argv[]) 
{ 
    int abc_def_ghi = 42; 
    #define SUFFIX ghi 
    #define VAR(prefix) prefix##_def_##SUFFIX 
    printf("%d\n" , VAR(abc)); 
    return 0; 
} 

// untitled:8: error: ‘abc_def_SUFFIX’ undeclared (first use in this function) 
+0

'const argv'? 처음에 나는 그런 것을 본다! 그 아이디어는 좋지만, 나는 그것을 좋아하는지 모르겠다. 그것은 '메인'을 부적합하게 만든다. 결코 내가하지 못한 일을하지 못하게한다.) – pmg

+2

부적합하지 않다. 'argv'는'char * argv []'(C99 5.1.2.2.1)과 동등한 것으로 선언 될 수 있고,'main'이 무엇을 할 수 있는지를 제외하고는'const'를 추가하지 않습니다. 그것 (캐스트없이). non-const에 대한 포인터는 문제가없는 const에 대한 포인터로 변환 될 수 있다는 것을 기억하십시오. 포인터의 값이 같음 (6.3.2.3/2)을 비교한다는 사실에 기인합니다. –

+0

오른쪽, 감사합니다 마이클. 다른 방식으로 (const를 제거하는 것) 비 호환으로 만들 수 있습니다. 나는 그것을 좋아하기 시작했습니다! – pmg

답변

10

당신은 단지 추가 간접 필요가 중복 보인다하더라도

#include <stdio.h> 

int main(int argc , char const *argv[]) 
{ 
    int abc_def_ghi = 42; 
    #define SUFFIX ghi 
    #define VAR3(prefix, suffix) prefix##_def_##suffix 
    #define VAR2(prefix, suffix) VAR3(prefix, suffix) 
    #define VAR(prefix) VAR2(prefix, SUFFIX) 
    printf("%d\n" , VAR(abc)); 
    return 0; 
} 

을, 그렇지 않아.

+0

그 이유를 설명해 주시겠습니까? – liori

+0

'6.10.3.3 ## 연산자 '에 대한 표준어를 이해하려고 시도하기에는 너무 늦었습니다. 그러나 어딘가에 그 이유를 설명합니다. (pdf @ http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1401.pdf) – pmg

+1

매크로 교체 목록은 매개 변수가 교체되기 전에 매크로 대체 대상이 아니기 때문에 # 및 ## 연산자가 적용되었습니다.따라서 질문자 코드에서'def _ ## SUFFIX'는'SUFFIX'를'ghi'로 대체 할 기회 전에'def_SUFFIX'로 대체됩니다. caf의 코드에서,'suffix'가 VAR2에서'SUFFIX'로 대체 될 때, 인수는 매크로 확장 (6.10.3.1/1)의 첫 번째 주제가됩니다. 결과는'abc_def_ghi'를 산출하는'VAR3 (abc, ghi)'입니다. ## 다음의 파라미터는 확장되지 않기 때문에 ('6.10.2.1/1)'VAR3 (abc, SUFFIX)'는 여전히'abc_def_SUFFIX'를 제공합니다. –

7

문자열 처리 (#) 또는 토큰 붙여 넣기 (##) 사전 처리 연산자를 올바르게 사용하는 일반적인 관용구는 2 단계 간접 지정을 사용하는 것입니다. (What are the applications of the ## preprocessor operator and gotchas to consider?). 그런 다음

#define STRINGIFY2(x) #x 
#define STRINGIFY(x) STRINGIFY2(x) 

#define PASTE2(a, b) a##b 
#define PASTE(a, b) PASTE2(a, b) 

:

int main(int argc , char const *argv[]) 
{ 
    int abc_def_ghi = 42; 
    #define SUFFIX ghi 
    #define VAR(prefix) PASTE(prefix, PASTE(_def_, SUFFIX)) 
    printf("%d\n" , VAR(abc)); 
    return 0; 
} 

당신에게 당신이 찾고있는 결과를 제공해야합니다.

기본적으로 매크로 교체 전에 ### 연산자의 처리가 발생합니다. 그런 다음 매크로 대체가 다시 발생합니다. 따라서 매크로를 해당 작업과 함께 사용하려면 교체 만 수행하는 1 단계를 사용해야합니다. 그렇지 않으면 문자열 또는 붙여 넣기가 먼저 발생하고 매크로는 더 이상 매크로가 아닙니다. stringizing/pasting이 생성됩니다.

더 직접적으로 - 매크로의 첫 번째 레벨은 매크로 매개 변수를 대체하고 두 번째 매크로 대체 수준은 stringify/token-pasting 작업을 수행합니다.

+0

와우, 고마워, STRINGIFY도 내가 가진 다른 문제를 해결. –

0

충분한 수준의 간접 지정과 함께 작동합니다.

#define SUFFIX ghi 

#define VAR1(prefix) prefix##_def_##SUFFIX 
VAR1(abc) 

#define VAR2_(prefix, sfx) prefix##_def_##sfx 
#define VAR2(prefix) VAR2_(prefix,SUFFIX) 
VAR2(abc) 

#define VAR3_(prefix, sfx) prefix##_def_##sfx 
#define VAR3x(prefix,sfx) VAR3_(prefix,sfx) 
#define VAR3(prefix) VAR3x(prefix,SUFFIX) 
VAR3(abc) 

저장이 텍스트 파일, x.c이며, 단지 그것을 사전 처리 : 다른 대답은 충분히 적합 동안, 나는 데모로이 코드 덩어리를 제공합니다.

gcc -E x.c 

관찰하고 숙고하십시오. 나는 그것을 완전히 이해하지 못한다. stringify를 사용하여 매크로를 작성하는 데 2 ​​시간을 소비하면됩니다. 두 배 우회가 때때로 필요하다는 것을 보는 것은 흥미 롭습니다.

+0

내가 할 abc_def_SUFFIX abc_def_SUFFIX abc_def_ghi 는 매크로 교체의 순서와 관련이있다처럼 스티브의 설명을 바탕으로, 소리가 난다. –