2011-01-27 2 views
12

C/C++로 작업 한 대부분의 사람들은 전처리 기가 어떻게 작동하는지에 대한 직감을 가지고 있다고 생각합니다. 나는 오늘까지 그렇게 생각했지만, 나의 직감은 틀린 것으로 판명되었습니다. 이야기가 있습니다 :(이상한?) GCC 전 처리기 동작

오늘 나는 무언가를 시도했지만 그 결과를 설명 할 수는 없습니다. 먼저 다음 코드를 고려하십시오.

#define A B 
#define B A 

A 
B 

어떻게됩니까?

A 
B 

글쎄, 좋아, 어쩌면 누군가가 기대하지 무엇을, 그러나 설명 할 수 있습니다 : 글쎄, -E 플래그로 컴파일 후 결과가 이것이다. 전처리 기는 어떻게 든 문제가 있다는 것을 알아 냈고,하지 않았습니다. 나를 위해, 설명 할 수없는 결과를받는 지금

#define A B 
#define B A C 
#define C x 

A 
B 

:

A x 
B x 

어떻게 이런 일이 않았다 내가 노력

다음 일이 있었다? 어떻게 된 일인지 알 수는 없습니다. 첫 번째 명령 (#define A B)은 실행될 수 없습니다. 왜냐하면 A가 B로 대체 될 것이므로 최종 결과는 두 명령 모두 동일해야하기 때문입니다. 그러나 그렇지 않다면 "A x"가 일어날 수있는 방법이 없습니다!

내 질문 : 무엇이 누락 되었습니까? 분명히 나는 ​​전처리 기가 어떻게 작동하는지 정확한 방법을 모른다. 그것에 관한 소식을 알고 있습니까?

+0

그리고 이것이 #define이 피할 필요가있는 이유입니다 ... – Goz

+0

네, 다른 이유입니다. 전혀 사용하지 않는 것이 아닙니다. 일부 작업의 경우 매우 유용합니다 (i.m.o로가는 길). – George

답변

13

Self-Referential Macros 설명합니다. 확장은 깊이 적용되지만 매크로가 참조되면 중단됩니다.

+0

친절하고 유용한 링크, 감사합니다! – George

5
#define A B 
#define B A C 
#define C x 

A -> B -> A C -> A x 
B -> A C -> B x 

확장 "느리게"

3

글쎄, 좋아, 어쩌면 누군가가 기대하지 어떤 토큰에 의해 토큰이지만, 설명 할 수 있습니다. 나는 전처리 기가 여하튼 어떤 문제가 있다는 것을 이라고 생각하고 하지 않았다고 생각한다.

아니요. 전 처리기가 확장을 수행하면 심볼을 한 번만 확장합니다. 따라서 A에 대한 첫 번째 예제에서는 A가 B로 확장되고 B는 A로 확장되며 여기서 확장이 중지됩니다. 두 번째 줄에서 B는 A로 확장되어 B로 확장됩니다. 여기서 B는 이미 확장 되었기 때문에 확장이 중지됩니다.

두 번째 예제에 논리를 적용하면 결과가 즉시 명확 해집니다.

5

각 대체 체인은 매크로 정의를 한 번만 방문 할 수 있습니다. 무엇보다도 이것은 재귀 매크로를 가질 수 없다는 것을 의미합니다. 두 번째 예를 들어

대체는 다음과 같이 표시됩니다

A --[evaluate A]--> B --[evaluate B]--> A C --[evaluate C]--> A x 
B --[evaluate B]--> A C --[evaluate A,C]--> B x 

을 첫 번째 줄의 마지막 단계에서, A는 이미 이전에 호출하기 때문에 평가되지 않습니다. 마찬가지로 두 번째 줄의 평가는 첫 번째 단계에서 이미 방문했기 때문에 B에서 중지됩니다.

C99 표준의 관련 섹션은 6.10.3.4 재검색 및 추가 교체입니다.

+0

설명 주셔서 감사합니다! 나는 문법과 언어의 맥락에서 생각하고 있었고 나는 그 명백한 설명을 완전히 놓쳤습니다. – George