전처리와 전처리 지시자
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 상수 사용이 권장됨
매크로는 주로 헤더파일 설정값, 조건부 컴파일 등에 사용