본문으로 건너뛰기

전처리와 전처리 지시자

C 컴파일 과정에서 가장 먼저 실행되는 전처리 단계
#으로 시작하는 지시문을 해석하여 소스코드로 변환한다.

전처리기(Preprocessor) 역할

  • 소스코드 컴파일 전에 #으로 시작되는 명령어 처리
  • 매크로 치환, 조건부 컴파일, 파일 포함 등 수행
  • 전처리 결과는 .i 확장자의 중간 파일로 저장 가능

전처리는 컴파일 전 소스코드를 확장·치환하는 과정이다.
소스코드가 컴파일러에 전달되기 전에 완전히 준비된 형태로 변환

주요 전처리 지시자

지시자설명
#define매크로 정의
#undef매크로 해제
#include파일 포함
#ifdef매크로 정의 여부 확인
#ifndef매크로 미정의 여부 확인
#if, #elif, #else, #endif조건부 컴파일
#pragma구현 종속 지시자 (컴파일러 설정용)

매크로(Macro)

전처리기의 치환 규칙을 정의하는 기능

컴파일 전에 코드 일부를 문자 그대로 바꿔치기 하는 도구

  • #define 지시자를 사용해서 정의
  • 함수처럼 동작하나, 함수가 아닌 단순 문자열 치환임
  • 성능상 빠르지만, 디버깅이 어렵고 타입 체크가 불가능

단순 매크로

#define PI 3.14

printf("%f", PI); // 3.14
  • PI 라는 이름을 3.14로 문자열 치환한다.

함수형 매크로

#define SQUARE(x) (x * x)

printf("%d\n", SQUARE(3)); // (3 * 3) -> 9
printf("%d\n", SQUARE(1 + 2)) // (1 + 2 * 1 + 2) -> 5 // x 대입식 괄호 적용 안됨!
  • 함수처럼 보이지만 실제로는 코드 조각을 문자 그대로 대입한다.
  • 연산자 우선순위 문제를 피하기 위해 괄호를 반드시 써야 함

조건부 컴파일

#define DEBUG
#define LEVEL 3

#ifdef DEBUG
printf("DEBUG MODE");
#endif

#if LEVEL == 3
printf("LEVEL 3");
#endif
  • 매크로 정의여부 혹은 조건식에 따라 조건문 내 코드 실행
  • 같은 방식으로 조건부 매크로 정의도 가능

매크로 정의 해제

#define PI 3.14
#undef PI // 이후 PI는 정의되지 않은 상태
  • 동일한 매크로 이름으로 인한 충돌을 피하기 위해 사용
  • 코드 영역을 한정해야 할 때 사용

매크로 vs 상수

  • 매크로는 문자열 치환이기 때문에 오류 검출 및 디버깅 어려움
  • 상수는 타입 검사 가능, 디버깅 및 유지보수 용이

안전성과 가독성 측면에서 const 상수 사용이 권장
매크로는 주로 헤더파일 설정값, 조건부 컴파일 등에 사용