Info
X-Macro를 알고 사용하는 도중,
#include나#define과 같은 동작의 순서와 구체적 동작을 잘 이해하지 못한다고 생각해서 이에 대해서 알아본 것을 토대로 작성한 글이다.
먼저 이제껏 컴파일된 파일이 각각의 ‘오브젝트 파일’로 구성된다는 것은 알고 있었지만, 세부 과정에 대해서는 막연하게 생각하고 넘어간듯하다.
이에 대해서 보자 명확하게 집어보자.
전처리(preprocessing)에서 처리되는 순서는 다음과 같다.
#include를 처리한다.#define메크로를 처리한다.#if,#ifdef, etc. 와 같은 컴파일 분기를 처리한다.
이를 증명하는 예제는 다음과 같다.
/* main.cpp */
#define B
#include "functions.hpp"
int main() {
printHello();
printBye();
return 0;
}
/* functions.hpp */
#pragma once
#define X(name, text) void name();
#include "functions.def"
#undef X
/* functions.cpp */
#define X(name, text) void name() { std::cout << text; }
#include "functions.def"
#undef X
/* functions.def */
#ifdef A
X(printHello, "Hello, world!\n")
#endif
X(printBye, "Goodbye!\n")위 예제를 다음과 같은 명령어로 처리한다.
g++ -E -P main.cpp -o main_preprocessed.cpp
g++ -E -P functions.cpp -o functions_preprocessed.cpp 출력 파일은 다음과 같다.
/* main_preprocessed.cpp */
void printBye();
int main() {
printHello();
printBye();
return 0;
}
/* functions_preprocessed.cpp */
void printBye() { std::cout << "Goodbye!\n"; }위 코드에서 #include로 정의한 파일의 전체 내용을 가져와 붙여넣고, 이를 #define으로 정의한 코드로 대체하는 것을 확인할 수 있다.
이렇게 전처리 단계가 모두 마무리된 데이터를 Translation Unit이라고 한다.
컴파일러는 이후 TU파일을 컴파일하여 오브젝트 파일로 만들고 이를 링킹하여 프로그램을 만들게된다.