2014-12-28 12 views
1

일부 매크로 정의를 네임 스페이스에 사용하면 네임 스페이스 외부에서 작동해야하는 이유는 무엇입니까? 다음 코드를 확인하십시오 :왜 C++ 네임 스페이스 내부의 정의가 네임 스페이스 외부에서 작동합니까?

#include <bits/stdc++.h> 

namespace foo { 
    #define a x*2 

    int f(int x) { 
     return a; 
    } 
} 

int main() { 
    int a = 50; 
    std::cout << a << endl; 

    std::cout << foo::f(4) << endl; 

    return 0; 
} 

여기 네임 스페이스 foo를 사용하여 작성한 적이 없습니다. 하지만 int를 선언하려고하면 이전에 정의 된대로 방해를 받기 때문에 여전히이 코드는 컴파일되지 않습니다. 그러나 이것이 왜 일어나야 하는가?

답변

6

"... int를 선언하려고하면 이전에 정의 된 A로 인해 방해 받지만 왜 이런 일이 발생해야합니까?"

#define 문은 네임 스페이스의 어떤 개념 (또는 다른 C++ 언어 구조)가없는 C/C++ 프리 프로세서에 의해 해석됩니다.

namespace foo { 
    #define a x*2 

    int f(int x) { 
     return a; 
    } 
    #undef a 
// ^^^^^^^^ 
} 
+0

re "또는 다른 C++ 언어 구문"으로 사용하기 위해 '# if'조건으로 사용하기 위해 전처리 기는 C 표현식의 하위 집합을 지원합니다. 이러한 표현에는 C++의'false' 및'true' 리터럴은 포함되지 않습니다. 실전 테스트를 위해 g ++가이를 수용하지만 Visual C++은이를 수용하지 않습니다. –

+0

이 답변은 정확합니다. 그러나 용어를 확장하고 싶습니다. 선행 처리 단계는 구문 분석 전에 발생하며 기술적으로 특수 언어를 처리합니다. IE의 모든 지시문 (예 :'#include ')이 확장 된 후 결과 처리 된 소스가 파싱되고 AST (추상 소스 트리)가 생성됩니다. 'gcc -E'를 호출하여 사전 처리 된 출력을 덤프 할 수 있습니다. –

+0

@os_ IMHO는 충분히 명확합니다 (적어도 받아 들여졌습니다). 개선하기 위해 편집하려고 할 수 있습니다. –

4

사전 프로세서는 네임 스페이스 또는 범위 지정과 같은 높은 수준의 언어 기능의 아무것도 모르는 :

당신이 정의의 범위를 제한하려면

#undef 지시어를 사용합니다. 그냥 #으로 시작하는 줄을 찾은 다음 간단한 텍스트 바꾸기를 수행합니다. 이것이 #include이나 파일 가드를 위해 전 처리기를 사용하는 것이 C++에서 위험한 이유 중 하나입니다.

3

#define은 C++ 범위를 존중하지 않습니다. "local" #define과 같은 것은 없습니다. #undef-ed 일 때까지 적용됩니다.

namespace foo { 
    #define a x*2 

    int f(int x) { 
     return a; 
    } 
    #undef a    <<<<<<<<<<<<<<<<<<<<< 
} 
1

프리 프로세서는 거의 자체 언어입니다. 먼저 실행됩니다. 매크로는 실제 C/C++ 컴파일러로 전달되는 코드를 생성합니다. 매크로를 사용할 때마다 항상 중괄호를 포함하여 매크로가 모든 것을 처리한다는 것을 기억하십시오. #undef와 같은 다른 전 처리기 지시문 만 매크로를 중지 할 수 있습니다.

BTW를 사용하면 모든 텍스트 파일에 C 전처리기를 단독으로 사용할 수도 있습니다.