[열혈C프로그래밍] chapter 23. 매크로와 선행처리기(Preprocessor)

chapter 23

매크로와 선행처리기(Preprocessor)

선행처리란?

컴파일 이전 선행처리란 과정이 있다.
이는 소스코드를 단순치환하여 소스코드의 일부를 수정하는 단계이다. (간단하다.)

# define PI 3.14
#define PRINT_ADDR puts("주소: 경기도 용인시\n"); // 이렇게 함수의 호출문도 매크로로 정의할 수 있다.

int main(void){
  num =3*PI; //선행처리를 거치면 num = 3*3.14; 로 단순치환된다.
  PRINT_ADDR; //선행처리를 거치면 puts("주소: 경기도 용인시\n"); 로 단순치환된다.
}

=> 이 코드처럼 선행처리기는 define(지시자)된 구문의 PI를 소스코드에서 찾아 3.14로 치환하는 역할을 한다.
#가 있는 코드들은 모두 선행처리기가 해결한다. 따라서 #include <stdio.h>도 선행처리기가 처리함을 알 수 있다.
또 #의 구문은 컴파일러가 아닌 선행처리기가 처리되므로 구문에 ;(세미콜론)이 붙지 않는 것이다.(명심)

#define은 크게 ‘매크로 상수’와 ‘매크로 함수’가 있다.

#define: Object-like macro

# define PI 3.14

PI를 매크로라 하고 3.14를 매크로 몸체라 하는데,
이 구문이 있다면, 소스코드의 모든 PI는 선행처리기에 의해 3.14로 치환된다.
매크로의 이름은 대문자로 정의하는 것이 일반적이다.

#define: Function-like macro

동작방식이 함수와 유사하여 function-like macro 라고 하는데 보통 매크로 함수라 한다.

#define SQUARE(X) X*X

이 매크로를 접한 선행처리기는 소스 코드에서 SQUARE(X)의 구문을 만나면 무조건 XX로 치환한다.
예를 들어, SQUARE(3)이 라는 코드가 있다면 선행처리기는 3
3으로 치환해버리는 것이다.

조건부 컴파일(Conditional Compilation)을 위한 매크로

#if… #endif: 참이라면

만약 # if 오른쪽에 true(1)이면 #endif까지 읽혀져 실행되고,
# if 오른쪽에 false(0)이면 #endif까지 읽혀지지 않아 실행되지 않는다.

#ifdef… #endif: 정의되었다면

# ifdef 는 매크로가 정의되었느냐 정의 되지 않았으냐를 기준으로 동작한다.
매크로가 참이냐 거짓이냐는 중요한 게 아니다.따라서 따로 1(true), 0(false)를 쓰지 않는다.

#ifndef… #endif: 정의되지 않았다면

# ifndef는 # ifdef와 반대로 정의되지않았다면 #endif까지 실행되는 매크로이다.
만약 정의되었다면, #endif까지 실행되지 않는다.