[KNK] CH14 - The preprocessor
CH14 - The preprocessor
preprocesser는 어떻게 작동하는가
#있는 문장이 오면 대체한다. #include로 헤더파일 앞에 있는 함수들울 앞에다가 그대로 복사하고 #define으로 매크로를 그대로 대체한다.
Preprocessing Directives
- Macro definition: #define
- File inclusion: #include
- Conditional compilation: #if, #ifdef, #ifndef, #elif, #else, #endif
\기호로 줄이 넘어가도 사용 가능
매크로 정의
- #define identifier(capitalized) replacement-list
- #define identifier(parameter’s) replacement-list (이경우 전처리과정에서 대체가 안된다)
(주의) parameterized macro의 경우 매개변수마다 괄호를 붙이고 매크로 전체에 괄호를 붙인다.
#define MAX(x,y) ((x)>(y)?(x):(y))
#define IS_EVEN(n) ((n)%2==0)
매크로와 함수의 장점
- 매크로가 좀더 빠름
- 변수가 좀더 generic
매크로와 함수의 단점
- 컴파일코드가 길어질 수 있음
- augments are not type-checked
- 포인터사용 못함
- augment 계산이 여러번 될 수 있음
MAX(i++,j)=( (i++) > (j) ? (i++) : (j) )
# operator
매개변수를 string literal로 만든다.
#define PRINT_INT(n) printf(#n "= %d\n",n)
PRINT_INT(i/j);
printf("i/j" "= %d\n",i/j);
parameterized macro가 #operator를 nest한 상황에서는 쓸 수 없다.
#define N 10
#define STR(x) #x
STR(N)="N"(not "10")
##operator
token을 붙인다.
#define MK_ID(n) i##n
int MK_ID(1), MK_ID(2);
int i1, i2;
parameterized macro가 nest한 상황에서는 쓸 수 없다.
#define CONCAT(a,b) a##b
CONCAT(a,CONCAT(b,c)) => aCONCAT(b,c)
매크로의 일반적 특징
다른 매크로를 쓸 수 있다. #define DOUBLE_PI (2*PI) #undef로 매크로 해제가 가능
comma(,) operator
함수, 함수;
Predefined Macros
__LINE__ //줄표시
__FILE__ //파일 이름표시
__DATE__ //"Mmm dd yyyy"
__TIME__ //"hh:mm:ss"
__STDC__ //표준(c89 or c99)을 따르면 1
__STDC__HOSTED__(c99) //c99표준을 반드시 따르면 1(hosted)/ 0(freestanding)
__STDC_VERSION__(c99) //yyyymmL(long integer of the date of amendment of the c)
__STDC_IEC_599__ //??
__STDC_IEC_599_COMPLEX__ //??
__STDC_ISO_10646__ //??
Empty Macro Arguments(c99)도 가능하다(w/o parameter)
Macros with a variable number of arguments(c99)
#define TEST(condition, ...) ((condition)?\
printf("Passed test: %s\n", #condition): \
printf(__VA_ARGS__))
// __VA_ARGS__는 나머지 ...에 있는 parameter들을 그대로 내보낸다
TEST(voltage<=max_voltage,"Voltage %d exceeds %d",voltage,max_voltage);
// if true -> Passed test: voltage <= max_voltage
// if false -> Voltage 125 exceeds 120
__func__ Identifier(c99) //not related with preprocessor!!
// string literal, unnecessary declaration
Conditional Compilation
#if, #endif, #elif, #else
#if constant_expression //시작
// condition에 따라 존재여부 결정
// statement....
#elif constant_expression
// statement....
#else
// statement...
#endif//끝맺음
‘defined’ operator
#if defined(DEBUG)(또는 #if defined DEBUG) //DEBUG의 정의 여부를 따짐
statement
#endif
#ifdef와 #ifndef
// identifier가 정의 됐을 때
#ifdef identifier
#if defined(identifier)
//identifier가 정의되지 않았을 때
#ifndef identifier
#if !defined(identifier)
#ifdef와 \if defined의 차이점: #ifdef or #ifndef와 달리 defined는 &&, || 연산자를 사용할 수 있다.
Uses of conditional Compilation
- 여러 종류의 머신과 OS에서 작동하도록 함
- 여러 종류의 컴파일러에서 컴파일 되도록 함
- 컴파일 시점에 매크로를 정의하여 특정코드가 컴파일 되지 않도록 함
Miscellaneous Directives
#error
#error message(printed message vary from one compiler to another)
#line
- #line은 LINE__과 __FILE(생략가능)매크로를 재정의
- #line 1 “abc.c”: 다음행부터 LINE__은 1부터 시작, __FILE=”abc.c”
- 프로그래머들이 사용 잘 안함
#pragma
- #pragma tokens : 컴파일러 지시용, 컴파일러마다 문법이 다름
- #pragma tokens=_Pragma (“tokens”) (c99)
댓글남기기