ANSI 표준에 따른 C의 전처리문의 종류
- 파일 처리를 위한 전처리문 : #include
- 형태 정의를 위한 전처리문 : #define, #undef
- 조건 처리를 위한 전처리문 : #if, #ifdef, #ifndef, #else, #elif, #endif
- 에러 처리를 위한 전처리문 : #error
- 디버깅을 위한 전처리문 : #line
- 컴파일 옵션 처리를 위한 전처리문 : #pragma
조건 처리를 위한 전처리문은 어떤 조건에 대한 검사를 하고 그 결과를 참(0 이 아닌 값) 또는 거짓(0)으로
돌려준다.
#if : ...이 참이라면
#ifdef : ...이 정의되어 있다면
#else : #if나 #ifdef에 대응된다.
#elif : 'else + if'의 의미
#endif : #if, #ifdef, #infdef이 끝났음을 알린다.
#if ~ #endif
#if 구문은 if랑 아주 비슷하다. 이것은 어떠한 구문을 컴파일 할지 안할지를 지정할 수 있다:
#define A 1
#if A
source code ...
#endif
위 source code 부분은 컴파일이 된다. if문에서와 같이 참, 거짓을 구분하여 컴파일이 된다. 위에서 A값은 1 즉 0보다 큰 수이기 때문에 참인 것이다. 직접 아래와 같이 하면 거짓이기 때문에 source code 부분은 컴파일이 되지 않는다:
#if 0
source code ...
#endif
#ifdef ~ #endif
컴파일 할 때
#define MYDEF /* MYDEF는 값은 가지지 않았지만 어쨋든 정의는 되었다 */
#ifdef YOURDEF /* 만약 YOURDEF가 정의되어 있다면... */
#define BASE 10 /* BASE == 10 */
#elif MYDEF /* 그외에 MYDEF가 정의되었다면... */
#define BASE 2 /* BASE == 2 */
#endif
BASE는 상수 2로 치환되어 전처리기가 컴파일러에게 넘겨준다.
#ifndef 헤더명_H__ ~ #endif
헤더 파일이 겹치는 것을 막기 위한 일종의 매크로이다. 예를 들어, 헤더 파일에 어떤 클래스의 인터페이스 선언을 넣었다고 하자. 이 클래스 인터페이스에서 다른 파일의 프로토타입이 필요해서 다른 A 파일을 include 하고 있는데 이 헤더 파일을 include 하는 파일에서 A라는 헤더 파일을 이미 include 하고 있다면 두번 define한 것이 된다. 그러면 SYNTEX 에러가 난다. 그래서 그런 것을 막는 방법의 하나로 #ifndef을 사용한다. 이전에 include되어 있으면 #endif 쪽으로 점프해 버려 결국 한번 선언되는 것이다:
#include
#include
이렇게 두번 썼다고 하자. 그런데 앞에 이미 include를 했는데 밑에 또 한다면 문제가 된다. 컴파일러가 검사해야할 코드량도 많아진다. 그래서 stdio.h에는
#ifndef STDIO_H__
#define STDIO_H__
가 선언되어 있다. 만약 STDIO_H가 선언되어 있지 않다면 선언한다는 뜻이다. 그 뒤 (b)에서는 이미 (a)쪽에서 STDIO_H__ 을 선언한 상태이기 때문에 전처리기 쪽에서 무시해버린다. 그러므로 컴파일러는 (a)만 검사한다.
#defined
define이 여러 개 되어 있는지를 검사할 때 쓴다. 이것은 여러 개를 동시에 검사 할 수 있다:
#if (defined A) || (defined B)
#ifdef와 #if defined의 차이
#ifdef은 정의가 되어 있는지를 테스트 하기 때문에, 한번에 여러 개를 사용할 수 없다:
#ifdef name
여러 개가 정의되어 있는지를 테스트 하기 위해서 #if defined를 사용할 수 있다:
#if defined(MACRO1) || defined(MACRO2)
#if는 ||로 중첩해서 사용할 수 있다. 형식이, #if expression이므로 C 표현이 올 수 있다:
#if (MACRO1) || (MACRO2)
#error
소스 라인에 직접 에러 메세지를 출력한다. 전처리기가 #error 문을 만나면 그 즉시 컴파일을 중단하고 다음과 같은 에러 메시지를 출력한다:
ERROR : XXXXX.c ########: Error directive: 내용
- XXXXX.c --> 현재 컴파일 중인 파일 명
- ####### --> 전처리기가 #error 문을 만난 시점에서의 행 번호(헤더 포함)
#ifdef __LARGE__
#error This program must be compiled in LARGE memory model!
#endif
이 내용은 만일 프로그램이 LARGE 모델이 아니라면 "#error" 뒤에 표시된 메세지를 출력하고 컴파일을 중지하게 된다.
#line
이 명령은 소스 코드의 행 번호를 지정하기 위한 것으로 주로 컴파일러에 의해 미리 정의된 __LINE__과 함께 사용된다.
__LINE__과 __FILE__을 각각 행 번호와 파일 명으로 변경한다:
#include <stdio.h>
#define DEBUG
void main(void)
{
int count = 100;
#line 100 /* 다음 줄번호를 100으로 설정한다 */
/* <-- 이 줄의 번호가 100이다 */
#ifdef DEBUG /* <-- 이 줄의 번호가 101이다 */
printf("line:%d, count = %d\n", __LINE__, count);
#endif
count = count * count - 56;
#ifdef DEBUG
printf("line:%d, count = %d\n", __LINE__, count);
#endif
count = count / 2 + 48;
#ifdef DEBUG
printf("line:%d, count = %d\n", __LINE__, count);
#endif
}
Object-C