전처리기 : 프로그램을 컴파일 하기전 선행 처리되는 부분.
소스파일->전처리기->컴파일러->링커->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 |