소년코딩

01.11 - 전처리기 (preprocesser)

전처리기(preprocessor)는 프로그램을 컴파일할 때 컴파일 직전에 실행되는 별도의 프로그램이다. 전처리기가 실행되면 각 코드 파일에서 지시자(directives)를 찾는다. 지시자(directives)는 #으로 시작해서 줄 바꿈으로 끝나는 코드다.

전처리기는 컴파일러가 실행되기 직전에 단순히 텍스트를 조작하는 치환 역할을 하기도 하고, 디버깅에도 도움을 주며 헤더 파일의 중복 포함도 방지해주는 기능을 가진다.

Include

이전 포스트들에서 #include 지시자를 보았다. #include 를 하면 전처리기(prerocesser)는 포함(include)된 파일의 내용을 지시자의 위치에 복사한다. [전방 선언(forward declaration) 에 사용했었다.]

#include <filename>

<>는 컴파일러와 함께 제공되는 헤더 파일을 include 할 때 사용한다. 위 헤더 파일은 C++ 런타임 라이브러리의 헤더 파일로써 운영체제의 특별한 위치에 존재한다.

#include "filename"

""는 소스 파일이 있는 디렉터리에서 헤더 파일을 include 하도록 전처리기(preprocesser)에게 지시한다. 일반적으로 이와 같은 방법으로 자신이 작성한 헤더 파일을 include 한다.


Macro

#define 지시자를 사용해서 매크로(macro)를 만들 수 있다. 매크로는 입력을 출력으로 변환하는 방식을 정의하는 규칙이다.

매크로는 객체와 유사한 매크로(object-like macro)와 함수와 유사한 매크로(function-like macro)가 있다.

함수와 유사한 매크로(function-like macro)는 함수처럼 작동한다.

객체와 유사한 매크로(object-like macro)는 아래와 같이 두 가지 방법 중 하나로 정의한다.

#define identifier
#define identifier substitution_text

첫 번째 정의에서는 대체 텍스트가 없지만, 두 번째 정의에는 대체 텍스트가 있다. 지시자는 명령어가 아니므로 둘 다 세미콜론(;)으로 끝나지 않는다.

대체 텍스트가 있는 객체와 유사한 매크로 (Object-like macros with substitution text)

전처리기가 이 지시자를 발견하면 'identifier'은 앞으로 'substitution_text' 텍스트로 대체된다. 식별자(identifier)는 일반적으로 공백을 나타내는 밑줄을 사용하여 대문자로 모두 입력한다.

#define MY_FAVORITE_NUMBER 9

std::cout << "My favorite number is: " << MY_FAVORITE_NUMBER << std::endl;

전처리기(preprocessed)는 위 코드를 다음과 같이 치환한다.

std::cout << "My favorite number is: " << 9 << std::endl;
대체 텍스트가 없는 객체와 유사한 매크로 (Object-like macros without substitution text)

객체와 유사한 매크로는 대체 텍스트 없이도 정의할 수 있다.

#define USE_YEN

일반적으로 이 전처리 지시자는 조건부 컴파일(conditional compilation)을 하기위해 사용된다.


조건부 컴파일(Conditional  compilation)

조건부 컴파일 전처리 지시자를 사용하면 컴파일할 조건이나 컴파일하지 않을 조건을 지정할 수 있다.

#ifdef 지시자를 사용하면 전처리기가 이전에 # 이 정의되었는지 아닌지를 확인한다. 정의되었다면 #ifdef와 해당 #endif 사이의 코드가 컴파일된다. 그렇지 않으면 코드가 무시된다.

#define PRINT_JOE  // PRINT_JOE 정의

#ifdef PRINT_JOE
std::cout << "Joe" << std::endl;
#endif

#ifdef PRINT_BOB
std::cout << "Bob" << std::endl;
#endif

PRINT_JOE가 정의되었기 때문에  cout << "Joe" << endl;는 컴파일된다. 그러나 PRINT_BOB은 정의되지 않았기 때문에 cout << "Bob" << endl;는 무시된다.

#ifndefifdef의 반대다. 식별자(identifier)가 아직 정의되지 않았는지 확인한다.

#ifndef PRINT_BOB
std::cout << "Bob" << std::endl;
#endif

PRINT_BOB는 아직 정의된 적이 없기 때문에 "Bob"은 출력된다.


cpp 번역: 이 포스트의 원문은 http://www.learncpp.com/cpp-tutorial/110-a-first-look-at-the-preprocessor/ 입니다.


댓글 로드 중…

블로그 정보

소년코딩 - 소년코딩

소년코딩, 자바스크립트, C++, 물리, 게임 코딩 이야기

최근에 게시된 이야기