C++ 프로그램 컴파일 과정
1. 소스 파일 작성
소스 파일(.cpp) : C++ 문법에 맞게 논리적으로 작성된 프로그램
2. 선행처리기(preprocessor)에 의한 선행처리
- 전처리 지시자 처리 : 소스 코드 내에서 사용되는 매크로, 헤더 파일, 조건부 컴파일 등을 처리
- 주석 제거 : 소스 코드 내의 주석을 제거하여 컴파일 시 영향을 주지 않도록 처리합니다.
- 난독화 : 코드의 가독성을 낮추어 코드 분석을 어렵게 하는 난독화 기능을 제공합니다.
*전처리 지시자(Preprocessor directive)란?
# 기호로 시작하는 특별한 명령어를 의미
- #include: 다른 소스 파일을 현재 소스 파일에 포함시키는 역할
#include <iostream>
// iostream : C++에서 입력(input)과 출력(output)을 수행하기 위해
// 사용하는 표준 입출력 라이브러리를 정의하고 있는 **헤더 파일**
// **헤더 파일(Header file)** vs **소스 파일(Source file)**
// **헤더 파일** : 소스 파일에서 사용되는 선언을 포함, 보통 .h 또는 .hpp 확장자를 가짐
// **소스 파일** : 프로그램의 실제 코드를 포함, 보통 .cpp 또는 .cc 확장자를 가짐
- #define: 프로그램 내에서 사용되는 상수나 매크로를 정의하는 역할
- 코드의 재사용성을 높이는 역할
#define MAX 100000
// #define **지시자(Directive)**로,
// 상수 100000을 MAX라는 **식별자(Identifier)**로 정의
// **식별자(Identifier)** vs **변수(Variable)**
// **식별자** : 변수, 함수, 클래스, 구조체, 열거형 상수 등에 부여되는 이름을 의미
// **변수** : 프로그램에서 데이터를 저장하는 메모리 공간을 의미
- #ifdef, #ifndef, #else, #endif: 조건부 컴파일을 수행하는 역할
#include <iostream>
#define OPTION_A 1 // OPTION_A를 정의
#define OPTION_B 2 // OPTION_B를 정의
using namespace std;
// 1. ifdef 사용법
// OPTION_A가 정의되어 있을 때만 코드 블록을 컴파일함
#ifdef OPTION_A
void functionA() {
cout << "Option A is enabled." << endl;
}
#endif
// 2. ifndef, else 사용법
// OPTION_B가 정의되어 있지 않을 때만 코드 블록을 컴파일함
#ifndef OPTION_B
void functionB() {
cout << "Option B is not enabled." << endl;
}
#else
void functionB() {
cout << "Option B is enabled." << endl;
}
#endif
// 둘 다 정의되어 있지 않을 때만 코드 블록을 컴파일함
#ifndef OPTION_A
#ifndef OPTION_B
void functionC() {
cout << "Neither option A nor option B is enabled." << endl;
}
#endif
#endif
int main() {
#ifdef OPTION_A
functionA();
#endif
#ifdef OPTION_B
functionB();
#else
cout << "Option B is not enabled." << endl;
#endif
functionC(); // OPTION_A 와 OPTION_B가 정의되어 있지 않으면 실행 가능
return 0;
}
- #error: 컴파일 중에 오류 메시지를 출력하는 역할
#include <iostream>
#define MAX_NUMBER 1000
using namespace std;
int main() {
int number;
cin >> number;
// 입력된 값이 MAX_NUMBER보다 크면 에러 메시지 출력 후 컴파일 중단
#if (number > MAX_NUMBER)
#error "The number is too big."
#endif
cout << "The number is " << number << endl;
return 0;
}
- #pragma: 컴파일러에게 특별한 지시를 제공하는 역할
// 컴파일러에서 발생하는 4996 경고를 무시하라는 뜻
#pragma warning(disable: 4996)
// GCC 컴파일러에서 코드 최적화를 수행할 때, 최적화 수준을 3으로 지정
#pragma GCC optimize(3)
// VC++ 컴파일러에서 mylib.lib라는 라이브러리 파일을 링커에 추가
#pragma comment(lib, "mylib.lib")
// 구조체의 크기를 1로 지정
#pragma pack(push, 1)
struct MyStruct {
char a;
int b;
};
#pragma pack(pop)
3. 컴파일러(compiler)에 의한 컴파일
소스 코드(high level language)를 기계어 코드(low level language)로 변환하는 과정
과정
// 덧셈 예시
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(1, 2);
return 0;
}
- 어휘 분석(Lexical analysis): 소스 코드를 의미 있는 작은 단위인 토큰(Token)으로 분해
[int] [add]([int] [a], [int] [b]) { [return] [a] + [b]; }
[int] [main] () { [int] [result] = [add]([1], [2]); [return] [0]; }
// 대괄호 안의 문자열 : 토큰을 의미
// 대괄호 밖의 문자열 : 구분자
- 구문 분석(Parsing): 생성된 토큰들이 문법적으로 올바른 문장인지 확인
- 추상 구문 트리(Abstract Syntax Tree, AST)라는 중간 표현을 생성
PROGRAM
|
FUNCTION FUNCTION
| |
ADD MAIN
| |
ARGUMENTS STATEMENTS
/ \\ |
INT INT VARIABLE_ASSIGNMENT
| | |
a b result
|
FUNCTION_CALL
|
ADD
/ \\
1 2
- 의미 분석(Semantic analysis): 추상 구문 트리를 분석하여 프로그램의 의미를 파악
- 변수의 타입 검사, 함수의 인자 검사, 변수와 함수의 정의 여부 검사 등이 수행
- 오류가 나면, 해당 오류를 보고하고 컴파일 중단
- 중간 코드 생성(Intermediate code generation): 기계어 코드 생성 전, 코드 최적화(Optimization) 작업을 수행하고, 기계어 코드를 생성하기 위한 준비를 함
// x86 아키텍처를 기반으로 한 어셈블리어 코드 예시
int add(int a, int b) {
return a + b;
}
int main() {
int result;
push 2
push 1
call add
mov result, eax
xor eax, eax
ret
}
add:
mov eax, [esp+4]
add eax, [esp+8]
ret
- 기계어 코드 생성(Code generation)
- 여러 최적화 기술이 적용하여 중간 코드를 0과 1로 이루어진 기계어 코드로 변환
- 후 오브젝트 파일(확장자 .o 또는 .obj) 생성
4. 링커(linker)에 의한 링크
링커(linker) : 컴파일 과정에서 생성된 오브젝트 파일(Object File)이나 라이브러리 파일(Library File)을 연결하여 하나의 실행 파일(Executable File) 또는 라이브러리 파일로 만들어주는 도구
'IT_Study > C++' 카테고리의 다른 글
[C++] Prefix Sum, Segment Tree 구현 및 상세 설명 (0) | 2023.03.28 |
---|---|
[C++] Bit operation, 구조체를 활용한 Map 사용법 정리 (0) | 2023.02.23 |
[C++] Dynamic Programming (동적 계획법) 정리 (0) | 2023.02.21 |
[C++] Greedy Algorithm (욕심쟁이 알고리즘) 정리 (0) | 2023.02.20 |
[C++] Binary Search, Parametric Search, Two pointer 알고리즘을 활용한 문제 풀이 방법 (0) | 2023.02.19 |