반응형

 

전처리기 : 프로그램을 컴파일 하기전 선행 처리되는 부분.

 

소스파일->전처리기->컴파일러->링커->exe 파일 

 

 

전처리기는 

앞에 # 을쓰며 맨뒤에 세미콜론; 을 붙이지 않는다.

 

지시문: 전처리기 지시문들은 프로그램 소스를 쉽게 변경하고 다른 환경에서 컴파일하기 쉽게 만든다.

 

전처리 지시문들을 간단하게 사용법을 적어두었다. 

 

전처리기 지시문 종류: #include #define #error #import #pragma #elif #if  #undef #else #ifdef #line #using #endif #ifnedf

아래의 내용은 micro내용에 있음

 


#include

처음부터 계속해서 나오는 include은 한글로 포함하다 라는 뜻을 가지고있으며 

지시문의 선언된 지점부터 지정된 파일의 내용을 포함하도록 전처리기에 지시 하는 문장이다.

 

c언어를 처음 배웠을때 나오는 #include <stdio.h> 을 처음으로 접하는 지시문이였을겄이다. 

 stdio standard input output 의 약자로 입출력을위해 우리가 초반부터 사용해 오던 헤더파일 이다.

이처럼 다른 소스코드를 쉽게 추가하여 사용할수 있다.

 

include의 사용법으로는

 

350: #include <stdio.h>

351: #include "std.h"

 

이런식으로 사용한다.

위 코드의 경우 #include <stdio.h> 파일 내용과 "std.h" 파일내용을 350번,351번 아래부터 적용한다. 로 볼수있다.

보통은 맨위에 적어서 모를수도 있겠지만 코드의 라인에 맞추어 적용한다.

 

#include <> 와 "" 의 차이는 파일을 읽는 방법에서 차이가난다

 

 

<>  컴파일러 옵션의 경로에 따직른 위치에서 헤더파일을 찾는다.

       <d:\file\a.h> 와 같이 지정된 경로를 찾는다.

 

""     컴파일러인 경우 현재 정의한 위치의 파일을 찾아본다.

        파일에서 상위 파일로 올라가며 찾아본다.

        이후 <> 와 같이 지정된 경로에 따른 위치에서 찾는다.

         지정된 경로를 찾는다. 

    

 

지정된 경로 예시

이러한 식으로 명확한 경로를 묶은 경우 해당 경로만 검색한뒤 표준 검색을 무시한다.

 

그럼으로 직접 만든 헤더파일일 경우 " "으로 사용하는걸 볼수있다.

 

 


#define  매크로

define 은 쉽게 사용하기위한 식별자(별명) 으로 볼수있다.

 

#define IN int
#define pi 3.141592
#define multiplyPI(x)(x*pi)

 

 IN in = 50;
 cout<< multiplyPI(in);
 cout<< in*pi;

 

위 처럼 간단한 함수 상수 등을  간단한 이름으로 변경하여서 사용할수 있다.

 

위 상수와 비슷한 매크로는 상수는

간단하게 변경할수 있으며 3.14 와 같은 숫자를 보기좋게 PI 와 같이 사용하여 가독성을 높힐수 있다.

 

#define pi 3.141592

 

매크로 와 비슷한 함수의 경우 일반함수와 다른점이 몇가지 있다.

 

매크로는  코드가 기계어로 변경될때 일반 함수와 다르게 하드코딩 한것 처럼 확장되어 넘어간다.

#define PI 3.141592

 

int p = PI ;

일경우

p = 3.141592 와 같다.

 

일반함수와 다르게 함수 공간(stack frame)이 생성안되기 때문에 속도가 빠르고
변경시 매크로 부분이 선언했을때 처럼 변경되며 실행파일 크기가 늘어난다.

 

계산을 하고 나오는 함수와달리

define 함수 는 하드코딩 처럼 변경 해주는 것이기때문에 다르게 계산된다.

 

#define SQR(x) x*x

int main() {

	int x = 10;
	cout << SQR(10)<<endl;
	cout << SQR(x+10) << endl;
	cout << SQR(++x) << endl;
}

위 와 같이 실행했을경우

차례대로 

100

120

144

순서대로 출력된다.

이렇게 출력되는 이유는 일전에 계속말 한것 처럼 함수가 아니라 실행전 치환 해주는 것이기 떄문인다.

이말은 위으 코드는 결국 아래와 같이 변경된다는 뜻이다.

	cout << 10*10 << endl;
	cout << x + 10 * x+10 << endl;
	cout << ++x *++x << endl;

 

이를 방지해 주기위해

	cout << SQR((x+10)) << endl;

이런식으로 넣으면 정상적으로 400이 나온다

 

위 코드처럼 define의 경우 틀렸을때 쉽게 오류를 찾기 힘든경우가 있기에 조심해서 사용해야 한다.

 


#undef 

undef는 식별자의 정의를 제거하여 , 이후 컴파일러에서도 식별자를 인식하지 못한다.

 

undef 의경우 define 와 같이 사용하여 영역처럼 사용할수 있다.

#define SQR(x) (x)*(x)
int main() {

	int x = 10;
	cout << SQR(10)<<endl;
#undef SQR
	cout << SQR(++x) << endl; //err 식별자가 정의되어 있지 않습니다.
}

 


 

 #if     #elif   #else  #endif #ifdef #ifndef

전처리기  조건부 컴파일 지시자.

사용법의 경우 아래 이미지 처럼 일반 if , else if , else 문과 비슷하게 사용한다.

다른점은 #if문의경우 마지막에 #endif로 끝맺음을 지어줘야한다.

 

그리고 전처리기 에서 처리하는 지시문 이기때문에 

위의 이미지 처럼 회색 처리되며 컴파일 조차 되지않는다.

#if SQR(10) 처럼 define 함수를 쓸수도 있다.

 

여러 경우로 사용할수 있는데 

 

컴파일 되지않기 때문에 테스트 모드와 실행모드를 설정하여 다르게 동작하게 할때 사용할수있다.

 

 

#ifdef 와 ifndef 는 

식별자가 존재할경우 #if 와 같은 기능을 하지만 정의 되지않거나 제외되었을경우 #undef와 같은 기능을하여

제외한다.

 

이러한 기능으로 헤더파일 중복을 막을수 있다.

 

#ifndef HD_FILE

#define HD_FILE

 


#line

 

#line 은 미리 정의된 매크로 중 __LINE__  과 __FILE__을 변경한다.

22: cout << __LINE__ << endl;
23:#line 12 "hello.cpp"
24:cout << __LINE__  +","+ hello.cpp<< endl;
25:cout << __LINE__ << endl;

output : 

22

12

13

에러 났을경우 라인과 파일을 출력할수 있고 

특정 상황에 라인을 재정의 하여 마지막에 도달하였을경우

line의 수를 보고 어떤 방식으로 실행하였는지 확인할수 있다.


 

#using #import

 

 

  #import

GCC (C 컴파일러 에서는) include 의 중복을 피할수 있는 용도로 사용하지만

cpp msvc 에서의 #import 는.tlb .olb 와같이 COM 객체를 사용하기위해 형식 라이브러리 type library 를 불러오는데 사용합니다.

 

#using 은 dll 파일을 참조할수 있습니다.

#using 되는 구성 요소는 컴파일 시간에 가져온 다른 버전의 파일로 실행할 수 있으므로 클라이언트 애플리케이션에서 예기치 않은 결과를 제공할 수 있습니다.

 


#paragma 

파라그마는 많은 기능을 내포하고 있다.

 

뒤에 붙는 명령어에 따라 다른 기능을 가지고 있는데

예시로

pragma omp 의 경우 스레드 즉 병렬 처리 관련한 기능들을 가지고 있다.

#pragma omp parallel for num_threads(4) 처럼 사용하여  병렬 처리할수 있다

내부엔 mutex semapor lock 과 비슷한 기능들도 구현 되어있다.

#pragma omp parallel for num_threads(4)
    for (i = 0; i < SIZE; i++)
    {
        a[i] = i;
        printf_s("%d\n", a[i]);
    }

 

progma once  는 소스코드 파일을 컴파일할때 컴파일러에 헤더 파일이 중복되지 않도록 지정한다.

 

 

 


미리 정의된 매크로

 

__DATE__ : Mmm dd yyyy 형식의 상수 문자열

__FILE__ : 현재 소스 파일의 이름

__LINE__: 소스파일의 줄 번호

 

위 와 같은 사용하기 쉽게 미리 정의 해둔 매크로 들이 존재한다. 

 

visual studio 의 최신 미리정의된 매크로의 경우 

microsoft 의 공식문서에서 확인할수 있다.

https://learn.microsoft.com/ko-kr/cpp/preprocessor/predefined-macros?view=msvc-170 

 

미리 정의된 매크로

Microsoft C++ 컴파일러의 미리 정의된 전처리기 매크로가 나열 및 설명되어 있습니다.

learn.microsoft.com

 

 

 

 

전처리기 연산자 

#,#@,## 

 

# 문자열화 연산자

매크로 매개변수를 문자열 리터럴로 변환한다.

예제 learn.microsoft.com

 

#@ charizing 연산자

매크로 인수에서만 사용가능하며 인수를 작은따음표로 묶어 매크로가 확장될때 문자로 처리된다.

 

 

 

 

 

 

 

## 토큰 붙여녛기 연산자

아래 처럼 ## 을 사용하면 매크로가 확장되지않는다 

n이 인수로 전달 되는것이 아니라 실제 token9와 같이 작동한다.

숫자 10을 넣는경우 오류가 나는것을 확인할수 있다.

<cassert> 라이브러리

는 위에서 사용했던 매크로가 만들어져 있는 라이브러리다.

 

'언어 > C++' 카테고리의 다른 글

CPP 콘솔 미로 만들기  (0) 2023.11.15
c++ std::function 사용하기  (0) 2023.01.10
함수 포인터! (Function Pointer)!  (0) 2021.07.13
인라인 함수(Inline Function)  (0) 2021.06.15
네임스페이스  (9) 2021.05.18

+ Recent posts