본문 바로가기

BackEnd/C랑 C++

전처리기(preprocessor)와 매크로(macro)

C/C++언어를 사용하면서

define으로 상수나 문자열을 정의해본 적이 한 번쯤은 있을 것이다

 

#include <iostream>

#define MAX_SIZE 1024
#define MAIN_NAME "test main"

using namespace std;
int main(void)
{
    cout << MAX_SIZE << endl;
    cout << MAIN_NAME << endl;
    return 0;
}
CLI> ./test
1024
test main

 

이런 식으로 ㅋ 문자열이나 숫자를 대체할 때 많이 쓴다

근데 자주 쓰던 " #define "이란 이 친구가 생각보다 많은 기능이 있더라

그래서 정리해보려고 한다

 


1. 전처리기(preprocessor)

직역하자면 processor 이전이라는 뜻인데, 우리가 프로그램을 실행하면

프로세스를 실행한다고 하는데

프로세스가 실행되기 전에 먼저 처리되는 게 전처리기이다

 

 

나눔스퀘어 글씨체 스릉

 

우리의 고급 언어로 작성된 코드를 실행하는 데는 꽤 복잡한 과정이 있다

자세한 내용은 컴파일 과정을 살펴보길 추천한다

 

이 중 전처리기 과정은 실행 파일 생성하는 과정에서

소스 파일의 여러 지시문을 우선 처리하는 작업이다

 

코드 생성 X, 컴파일러가 컴파일 잘 할 수 있도록 소스를 재구성해주는 역할이다

 

전처리되는거는 어떤 게 있냐면

 

(1) 전처리 지시자

(2) Macro

(3) 조건부 컴파일 (Conditional compilation)

...

등등이 있다 ㅋ

사실 오늘 macro만 정리하려고 했는데 말이 계속 늘어나네;;

 


(1) 전처리 지시자 (preprocessing directives)

 

하여간 우리말은 너무 어려워

전처리 지시자라는 단어는 어려워 보이지만,

우리가 많이 쓰는 #include, #define, #pragma, #ifndef 등이다 ㅋ

 


#include

얘는 프로그램 파일의 위치를 첨부하여 하나의 파일처럼 컴파일해주고,

헤더 파일이나 다른 파일에 있는 선언 내용을 다른 파일끼리 연결해준다

사용 방식에는 두 가지가 있다 ㅋ

 

#include <iostream>
#include "MyClass.hpp"

 

표준 헤더 파일을 컴파일에 포함할 때는 <>를 사용하고

우리가 작성한 헤더 파일을 포함할 때는 ""를 사용한다

사실 섞어 써도 되긴 하는데, 표준(?)적인 문법이다

 


#define

얘는 글의 가장 첫 번째 예시에서 사용했는데, 상수/문자열/함수 등을 단순화해준다

define 자체는 정의하다는 뜻이지 않은가

좀 더 명확하게 이름을 붙여준다~라고 생각하면 된다

 

#define PERIMETER 3.14

int main(void)
{
		int n = 3.14;
		int n = PERIMETER;
...

 

이런 식으로? 그냥 상수 사용보다는 이름 붙여서 사용 ㅇㅇ


그 밖의 전처리 지시자는 링크를 참고하길 바란다

 


 

(2) 매크로 함수 (Macro function)

 

매크로는 직역하면 '거대한'이란 뜻인데,

마이크로(micro)의 반대되는 의미로 뭔가 하나의 큰 단위?라고 이해하면 된다

위에서 다룬 #define 지시자에 함수 정의를 전달해서 마치 함수처럼 동작하게 할 수 있다

 

#include <iostream>

#define PLUS(x) x+x
#define MUL(x) x*x

using namespace std;

int main(void)
{
	cout << PLUS(5) << endl;
	cout << MUL(5) << endl;
	return 0;
}

 

이런 식으로 사용 가능하다

함수처럼 인자를 전달해주는 모양으로 사용이 가능하다 ㅋ

 

#define MY_PRINT(x)\
do{\
	cout << "x는 " << endl;\
    cout << x << endl;\
}while(0)\

 

여러 줄이라면 do-while문을 사용해서 표현도 가능하다

끝에 "\"를 써서 개행 표시해주는 거도 잊지 마시길ㅋ

요놈 참 편리함

 

근데 위에 위에서 사용한 상수 계산식을

매크로 함수로 만들 때는 주의해야 할 점이 하나 있다

 

#include <iostream>

#define PLUS(x) x+x
#define MUL(x) x*x

using namespace std;

int main(void)
{
    int plus_ret = PLUS(5);
    int mul_ret = MUL(5+5);

    cout << plus_ret << endl;
    cout << mul_ret << endl;
    return 0;
}

 

CLI> ./test.out
10
35

 

롸? 왜 아래 꺼는 35로 찍힐까

10 * 10을 예상했겠지만.. 전처리기는 치환해줄 뿐이다

즉, MUL(X)는 5+5*5+5로 바뀌기 때문에 

사칙연산 우선순위에 따라 결과가 예상과 다르게 나온 것이다 ㅋ

그래서 상수식에 대해 매크로를 작성할 때는

 

#define MUL(x) (x)*(x)

 

이렇게 괄호를 묶어서 사용해야 한다

 


# 연산자 사용

전처리 지시자에는 #연산자를 사용하여 토큰 단위 연산을 사용할 수 있다

 

#include <iostream>

#define PLUS(X)\
    do{\
        cout << ""#X"의 덧셈은" << ((X)*(X)) << "입니다." << endl;\
    }while(0)\

using namespace std;
int main(void)
{
    PLUS(5);
    PLUS(3+4);
    return 0;
}
5의 덧셈은25입니다.
3+4의 덧셈은49입니다.

 

요런 식으로~~ # 큰따옴표 + 파라미터를 포함해서 사용하면

 문자열 상수로 변환해준다


 


(3) 조건부 컴파일 (Conditional compilation)

조건부 컴파일은 조건에 따라 컴파일한다라는 뜻인데

조건이 맞으면 처리하고 안 맞으면 안 처리한다는거겠쥬?

 

내가 가장 많이 쓰는 건 주석처리를 사용할 때다

 

#if ~ [#elseif] ~ [#else] ~ #endif

 

주석 처리한걸 좀 더 명확하게 보여드릴라고 캡처로 가져와봤다

결과는 3만 출력된다

 

#ifdef~ 조건 사용

 

우리가 코드를 짜다보면 운영체제에 따라서,

또는 어떤 라이브러리의 버전에 따라서 추가해야 할 헤더 파일도 달라지고

그럴 때가 있다... 근데 이때마다 코드를 수정하는 건 좀 그렇다 많이 그렇다

 

#ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */
# include <unistd.h>
#elif defined _WIN32 /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */
# include <windows.h>
#endif

 

이런 식으로 해주면, 윈도이건 유닉스이건

알아서 컴파일할 때 포함되어야 할 헤더 파일을 포함시켜 준다

 

#if RUBY_VERSION == 190
# error 1.9.0 not supported
#endif

 

이런 식으로 특정 조건이 아닐 때 에러를 뱉도록 해줄 수도 있다

그럼 이만

 


* 참고 링크 *

http://www.tcpschool.com/c/c_prepro_preprocessor

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

https://ko.wikipedia.org/wiki/C_%EC%A0%84%EC%B2%98%EB%A6%AC%EA%B8%B0

 

C 전처리기 - 위키백과, 우리 모두의 백과사전

매크로는 컴퍼일러에게 코드의 특성을 알려주는 키워드이다. 따라서 기계어로 컴파일 과정에서 필요한 요소이고, 매크로 자체가 기계어 코드로 생성되지는 않지만 특정 코드를 제어하는데 사

ko.wikipedia.org