안녕하세요. 명월입니다.
이 글은 C++에서 전처리문에 대한 글입니다.
전처리문이란 C++이 컴파일해서 실행되기 전에 처리되는 소스 메크로라고 생각하면 됩니다.
간단한 예를 들면 debug 상태에서 실행되어야 할 소스나 값이 있고 release 상태에서 실행되어야 할 소스나 값이 있는데 그걸 전처리문으로 처리할 수 있는 것입니다.
#include <stdio.h>
#include <iostream>
using namespace std;
// 실행 함수
int main()
{
// 전처리기 _DEBUG가 있을 경우 아래의 구문을 실행
#ifdef _DEBUG
// 콘솔 출력
cout << " DEBUG MODE " << endl;
// 전처리기 _DEBUG가 없을 경우 아래의 구문을 실행
#else
// 콘솔 출력
cout << " RELEASE MODE " << endl;
#endif
return 0;
}
위 예제를 보면 Debug 모드에는 콘솔 출력을 DEBUG MODE로 하고 Release 모드에서는 RELEASE MODE가 표시되게 설정하였습니다.
이는 ifdef는 define된 변수가 _DEBUG가 있을 때와 없을 때를 구분으로 실행하는 것입니다. 이 define은 프로젝트의 속성으로 가면 설정하는 탭이 있습니다.
전처리문의 종류는 총 12가지 정도 있습니다.
전처리기 | 설명 |
---|---|
조건부 포함 전처리문(Conditional inclusions) | |
#if | 전처리 분기문 if에 해당됩니다. define에 정의 값을 비교합니다. |
#elif | 전처리 분기문 else if에 해당됩니다. define에 정의 값을 비교한다. elif 전처리문 단독으로 사용할 수 없습니다. |
#else | 전처리 분기문 else에 해당됩니다. else 전처리문 단독으로 사용할 수 없습니다. |
#endif | 전처리 분기문의 종료에 해당합니다. |
#ifdef | define 전처기문이 정의되어 있으면 해당된다. |
#ifndef | define 전처기문이 정의되어 않으면 해당된다. |
매크로 정의 전처리문(macro definitions) | |
#define | 전처리 매크로 및 상수 정의 |
#undef | 정의된 전처리문을 무효화한다. |
디버깅 라인 전처리문(Line control) | |
#line | 이미 정의된 전처리문 __LINE__에 소스 정의 라인을 재정의하기 위한 전처리문 |
에러 탐지 전처리문(Error directive) | |
#error | Runtime 중이 아닌 compile 단계에서 일부러 에러를 발생시킬 때 사용한다. |
소스 포함 처리 전처리문(Source file inclusion) | |
#include | 보통 해더 파일을 읽을 때 사용합니다. 최종 빌드 전의 이진 파일이 아닌 소스 형태의 파일을 읽을 때 사용합니다. |
지시어 전처리문(Pragma directive) | |
#pragma | pragma는 세가지 형태로 사용된다. 가장 많이 사용되는 #pragma once는 해더를 여러 곳에서 참조할 경우 한번만 읽는 기능, 즉, a.cpp 소스에서 common.h를 읽고 b.cpp 소스에서 common.h을 읽을 려고 할 때 a.cpp에서 먼저 읽었기 때문에 두번 읽지는 않는다. #pragma comment(lib, 파일이름.lib) 등 해더 내에서 library 참조시에 사용된다. visual studio에 기본적으로 선언되어 있는 lib는 kernel32.lib, user32.lib, gdi32.lib, winspool.lib, comdlg32.lib, advapi32.lib, shell32.lib, ole32.lib, oleaut32.lib, uuid.lib, odbc32.lib, odbccp32.lib #pragma warning(disable:4702)는 4702의 에러를 무시해 주는 전처리 문입니다. |
사전 정의된 전처리문(Predefined macro names) | |
__LINE__ | 컴파일 중인 소스 코드 파일의 현재 행을 나타내는 정수 값입니다. |
__FILE__ | 컴파일 중인 소스 파일의 추정 이름이 포함 된 문자열 리터럴입니다. |
__DATE__ | 컴파일 프로세스가 시작된 날짜를 포함하는 "Mmm dd yyyy"형식의 문자열 리터럴입니다. |
__TIME__ | 컴파일 프로세스가 시작된 시간을 포함하는 "hh : mm : ss"형식의 문자열 리터럴입니다. |
__cplusplus | 정수 값. 모든 C ++ 컴파일러에는이 상수가 일정한 값으로 정의되어 있습니다. (컴파일러의 버젼과 비슷한 설정) |
__STDC_HOSTED__ | 구현이 호스팅 된 구현 인 경우 (모든 표준 헤더 사용 가능) 그렇지 않으면 0입니다. |
// 중복 읽기 금지 전처리문
#pragma once
// 소스 포함 전처리문
#include <stdio.h>
#include <iostream>
// 메크로 정의 전처리문
#define Squared(x) x*x
// 정의 전처리문
#define TEST
using namespace std;
// 시작 함수
int main()
{
// 라인 재설정
#line 1
#ifdef TEST
// 2의 제곱은 4이면
#if Squared(2) == 4
// 콘솔 출력
cout << " 2 Squared? " << 4 << endl;
// 2의 제곱은 5이면
#elif Squared(2) == 5
// 콘솔 출력
cout << " 2 Squared? " << 5 << endl;
// 그 외
#else
// 콘솔 출력
cout << " 2 Squared is unknown. " << 5 << endl;
#endif
// 콘솔 출력
cout << "Line is " << __LINE__ << endl;
#else
// 에러!
#error ERROR!!
#endif
return 0;
}
실행 결과입니다.
전처리문은 소스가 컴파일 되기 전의 소스 레벨에서 이루어지기 때문에 Visual studio를 보시면 이미 폰트의 색으로 어느 영역이 실행되는지 알 수가 있습니다. 그리고 전처리문은 Runtime레벨이 아닌 소스 레벨이기 때문에 사용하기에 따라서 성능을 향상시킬수도 저하시킬수도 있습니다.
물론 사양에 따른 이지만, 개인적인 생각은 전처리문과 template 기능을 잘 사용하면 성능을 놀라울 정도로 향상 시킬수 있고, 아예 새로운 언어 문법을 창조시킬 수도 있습니다.
여기까지 C++에서 전처리문에 대한 글이었습니다.
궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.
'Study > C , C++ , MFC' 카테고리의 다른 글
[C++] namespace와 using 사용법 (1) | 2020.03.20 |
---|---|
[C++] 접근 제한자, 추상 클래스(순수 가상 메서드), 오버로드(Overloading)와 오버라이딩(Overriding) (0) | 2020.03.20 |
[C++] 클래스 상속 (0) | 2020.03.19 |
[C++] 템플렛(Template) (2) | 2020.03.19 |
[C++] 클리스 선언과 사용법 (0) | 2020.03.17 |
[C++] 함수 사용법(가변 파라미터 stdarg.h, 함수 포인터 그리고 범용 포인터 void*) (0) | 2020.03.15 |
[C++] 배열과 포인터(메모리 주소) 그리고 할당(new){stack과 heap에 대해서} (0) | 2020.03.14 |
[C++] 제어문 (0) | 2020.03.12 |