본문 바로가기
C/[코드조선] C 핵심

[C] 조건부 컴파일과 매크로 함수

by 묻공러 2024. 2. 18.

조건부 컴파일
조건에 따라 특정 부분의 소스코드를 컴파일에 포함 혹은 배제시키는 문법이다

#ifndef NULL
#define NULL (0)
#endif
/* NULL이 정의 안되어있다면, 값이 0인 NULL을 정의. */
  
#if !defined(NULL)
#define NULL (0)
#endif
/* NULL이 정의 안되어있다면, 값이 0인 NULL을 정의. */
  
#if defined(NULL)
#undef NULL
#endif
/* NULL이 정의되어 있다면, 그 정의를 해제시킴. */
  
#define NULL (0)
/* 값이 0인 NULL을 정의. */

 

조건부 컴파일 주의점

#define A

#if defined (A) // 참
#define LENGTH (10)
#endif
        
#if A           // 거짓, A에 어떤 정의도 해주지 않았기 때문에
#define LENGTH (10)
#endif

 

인클루드 가드

헤더 파일들이 서로가 서로를 인클루드 하는 상황이 생길 수 있다
이를 순환참조(Circular Dependency)라고 부르며, 해결법 중 하나가 인클루드 가드이다

헤더 파일의 추가 가능 여부를 define으로 확인하는 것이다

#ifndef A_H      // 만약 A_H가 정의되어 있지 않다면,
#define A_H      // A_H를 정의
  
                 // 이 부분에 소스코드가 있다면, 해당 소스코드는 A_H가 정의되어 있지 않을 때 실행
  
#endif

 

인클루드 가드 예시

// apple.h

#ifndef APPLE_H
#define APPLE_H

#include "strawberry.h"

#endif // APPLE_H
// strawberry.h

#ifndef STRAWBERRY_H
#define STRAWBERRY_H

#include "apple.h"

#endif // STRAWBERRY_H
// main.c

#include <stdio.h>
#include "apple.h"

int main(void)
{
    
 
    return 0;
}

 

조건부 컴파일의 다양한 예시

- 버전 관리

int spawn_monster(...)
{
    get_monster_skin();
    get_monster_stat();
            
    #if defined(FILE_VERSION_2)
        use_custom_skin(...);
        /* 어딘가에 #define FILE_VERSION_2라는 코드가 없으면 컴파일에 포함 안됨. */
    #elif defined(FILE_VERSION_3)
        use_custom_voice(...);
    #else
        use_default_skin(...);
        use_default_voice(...);
    #endif
            
    calculate_spawn_location();
            
    return TRUE;
}

 

- 주석 처리

#if 0 /* 0을 1로 바꾸면 포함, 그냥 두면 주석. 편함. */

... 명령어 ...

#endif

 

- 에러

컴파일 도중 강제로 컴파일 에러 발생시키는 매크로이다
메세지를 꼭 큰 따옴표로 감싸지 않아도 된다

/* version.h [분할 컴파일]*/
#define VERSION 10

/* builder.h [분할 컴파일]*/
#if VERSION != 11
#error "Unsupported version."
#endif

 


 

매크로 함수
장점:

함수 호출이 아니라 소스코드 복붙의 개념이다

따라서 함수 호출에 대한 overhead가 없다

 

단점:

디버깅이 불가능하다

중단점이 걸리지 않는다

 

매크로 함수의 예시

매크로 사용 시 여러 줄을 사용해야 하는 경우

아래와 같이 \를 사용하면 된다

#include <stdio.h>

#define POW(n,e,i,r) r = 1;                    \
                     for (i = 0; i < e; ++i)   \
                     {                         \
                         r *= n;               \
                     }                         \

int main(void)
{
    int i;
    int num = 2;
    int exp = 8;
    int res;
    
    POW(num, exp, i, res);

    printf("%d", res);

    return 0;
}