
전처리 과정에서 #include 파일의 내용을 코드로 치환합니다. 또한 #define 부분을 코드로 치환합니다.
각 소스 코드들을 컴파일러가 어셈블리어로 읽을 수 있는 어셈블러 파일 *.s 파일로 변환합니다.
어셈블리어 파일을 컴파일러가 Object 코드로 변환합니다.
링크 과정을 통해 컴파일러가 생성한 Object 코드와 외부 라이브러리 파일들을 모아서 실행 파일을 생성합니다. ex) *.exe
소스 파일에 있는 문자들을 해석하는 과정입니다.
기본적으로 c++ 코드에서 제공하는 96개의 문자들로 이루어진Basic source character set이 존재합니다.
1. 대문자 알파벳 : 26개
2. 소문자 알파벳 : 26개
3. 숫자 (0 - 9) : 10개
4. 특수문자 : 29개
5. 공백문자 : 5개 (특수문자에 포함됨)
스페이스 (Space): ''
수평 탭 (Horizontal Tab): '\t'
새 줄 (Newline): '\n'
캐리지 리턴 (Carriage Return): '\r'
수직 탭 (Vertical Tab): '\v'
이를 제외한 다른 문자들은 유니코드 값으로 치환 또는 컴파일러에 의해 따로 해석됩니다.
#include에 지정된 파일의 내용을 복사합니다.#define에 정의된 매크로를 사용해서 코드를 치환합니다.#if, #ifndef와 같은 구문들을 실행해서 코드를 치환합니다.#pragma와 같은 컴파일러 명령문들을 해석합니다.
// 실행 전
#inlcude <iostream>
int main()
{
}
--------------------------------------------
// 실행 후
namespace std
{
...
}
namespace std
{
...
}
namespace std
{
...
}
.... 생략
전처리 단계가 끝난 이후 컴파일러가 보는 소스는 다음과 같이 변하게 됩니다.
#include로 복사된 헤더 파일은 다시 1번부터 4번까지의 과정을 거칩니다.
이와 같은 문제를 해결 하기 위해서미리 컴파일된 헤더(Pre Compiled Header)라는 개념이 도입되었습니다.
// 변경 전
std::cout << "abc"
"def";
// 변경 후
std::cout << "abcdef";
모든 변수, 함수 ,클래스 등등의 정의는 유일 해야하고, inline이 아닌 모든 함수의 변수들의 정의는 전체 프로그램에서 유일해야 한다. 이것이 유일 정의규칙입니다.
- 동일한 이름의 엔티티는 한 번만 정의되어야 합니다.
- 선언과 정의는 유일해야 합니다.
- 같은 구조체나 클래스가 서로 다른 헤더파일에서 정의되더라도, 내부 구현이 동일하면 문제가 없습니다.
// file1.cpp
int x = 5; // 정의
// file2.cpp
extern int x; // 선언
여기서 int x = 5;는 변수 x를 정의하는 것이며, extern int x;는 변수 x를 선언하는 것입니다.
이때 extern 키워드는 "이 변수는 다른 파일에서 정의되었음"을 나타냅니다. 이는 ODR을 지키고 있습니다.
// file.cpp
void myFunction() {
// 함수의 정의 내용
}
// file2.cpp
void myFunction(); // 함수의 선언
여기서 void myFunction() {...}는 함수 myFunction의 정의이며, void myFunction();는 함수 myFunction의 선언입니다.
함수를 사용하는 코드에서는 선언만 알고 있어도 됩니다.
ODR은 여러 파일에 함수를 정의하더라도, 컴파일러가 정의를 합칠 수 있도록 합니다.
// file1.cpp
class MyClass {
// 클래스의 정의 내용
};
// file2.cpp
class MyClass; // 클래스의 선언
여기서 class MyClass {...};는 클래스 MyClass의 정의이며, class MyClass;는 클래스 MyClass의 선언입니다.
클래스를 사용하는 코드에서는 선언만 알고 있어도 됩니다.
ODR은 여러 파일에 클래스를 정의하더라도, 컴파일러가 정의를 합칠 수 있도록 합니다.
컴파일러에게 변수, 함수, 클래스 또는 다른 프로그램 요소가 존재함을 알려주는 것입니다.
int x;
void func();
int x;
int x = 1;
void func()
{
x++;
}
정의는 변수, 함수, 클래스 등을 실제로 생성하고 메모리를 할당합니다.
정의는 선언에 포함됩니다.
모든 정의는 선언이다. (참)
모든 선언은 정의이다. (거짓)
extern const int a; // a 를 선언하였지만 정의하지 않음
extern const int b = 1; // b 를 정의함
하지만 extern 지정자가 들어간 선언의 경우 명시적으로 초기화 되지 않는다면 선언입니다.
struct S {
int n; // S::n 정의
static int i; // S::i 정의
inline static int x; // S::x 를 정의
}; // S 를 정의
클래스 정의 내부에 inline이 아닌 static 멤버의 경우에도 정의입니다.
전처리 과정에 대해서 설명해주세요.
C++에서 유일 정의 규칙에 대해서 설명하고 유일 정의 규칙이 성립하기 위한 조건을 자세하게 설명해주세요.
다음 예시에서
?에 해당하는 부분에 선언과 정의인지 말해주세요.
// 1.
extern int intVal; // ?
// 2.
struct S { // ?
int n; // ?
static int i; // ?
inline static int x; // ?
};
// 3.
class MyClass { // ?
static int x; // ?
};