본문 바로가기
프로그래밍 언어/C 언어

[C] [전처리기] 매크로와 선행처리기

by 까망 하르방 2025. 1. 28.
반응형

매크로와 선행처리기

실행파일이 컴파일과 링크의 과정을 거치는데 컴파일 이전에 선행처리 과정을 거친다.

▶ 선행처리 컴파일 오브젝트 파일 → 링크 실행 파일

※ 컴파일 과정에 포함해서 표현하기도 한다.

    한편으로는 컴파일러에 따라서 전처리 과정은 전처리기(preprocessor)라는

    별도의 프로그램으로 수행하기도 한다.

※ 소스코드가 선행 처리기를 거쳐도 별도의 파일이 생성되는 것은 아니다.

    소스파일을 유지 하며, 선행처리 명령문대로 소스코드의 일부를 치환할 뿐이다.

    - 컴파일: 오브젝트 파일 생성

    - 링커: 실행파일 생성

#include <stdio.h>

#define NAME "TEST"
#define PRINT_ADDR puts("주소: xxx-xxx");
#define SQUARE(X) X*X

int main(void){
    printf("%s \n", NAME); // TEST
    PRINT_ADDR; // 주소: xxx-xxx
    printf("%d", SQUARE(-5)); // 25
}

매크로로 정의되어 있는 부분이 치환된다.

 

매크로 함수는 성능을 높일 수 있지만 사용할 때 주의해야 할 것이 있다.

Q) #define SQUARE(X) X*X 부분에서 SQUARE(3 + 2)로 호출하면 결과는 어떻게 될까?

A) 원하는 결과는 (3+ 2) * (3 + 2) = 25이지만 실제 결과는 3 + 2 * 3 + 2 = 11이 됩니다. 

    이렇게 처리되는 이유는 (3 + 2)가 먼저 연산을 하고, 그 연산결과를 가지고 선행처리 되지 않기 때문이다.

    ※ 일반적인 함수라면 결과값을 가지고 인자가 전달된다.

 

이와 같은 경우를 처리하기 위해서는 

- SQUARE((3+2))로 호출

- 매크로 정의 자체를 #define SQUARE(X) (X)*(X)  모두 괄호 처리 해버리는 것이다.

 

 

Q) 두 줄 이상 사용한다면

매크로는 한 줄 정의가 원칙이기 때문에 

가독성을 위해 두 줄 이상에 거쳐서 정의할 경우

백슬러쉬(\) 이용하면 된다.

#define SQUARE(X)    \
        ((X)*(X))

 

 

매크로 함수 장단점

[장점]

일반 함수라면 함수를 스택 메모리에 할당, 매개변수 전달 등

빈번한 호출이 발생할 수 있지만 매크로 함수는 선행 처리기에 의해

호출 문장을 대신하므로 실행 속도가 빠르다.

또한, 자료형에 따라서 별도 함수를 정의하지 않아도 된다.

// 일반 함수
int DiffABS(int a, int b){
    if(a > b) return a-b;
    else return b-a;
}

// 매크로 함수
#define DIFF_ABS(X,Y) ((X)>(Y) ? (X)-(Y) : (Y)-(X))

 

 

[단점]

정의하기 까다롭다.

디버깅하기가 쉽지 않다. 

 

즉, 매크로 함수는

작은 크기의 함수나 호출의 빈도수가 높은 함수에 유용하다고 할 수 있다.

 

 

반응형

댓글