2010-1 학기프로그래밍입문 (1) 8 장전처리기 박종혁 Tel: 970-6702 Email: jhpark1@snut.ac.kr 0
전처리기 C 언어는전처리기를사용하여그능력과표기법을확장함 # 으로시작하는행을전처리지시자라고함 #include #define #if #error ANSI C 에서 # 은여백문자다음에올수있지만, 전통적인 C 에서는첫번째열에 # 이와야만함 A Book on C, 4ed. 8-1
전처리기 전처리지시자를위한구문은 C 언어의나머지부분과독립적임 전처리지시자가영향을미치는범위 - 그파일에서전처리지시자가있는위치에서시작여그파일의끝까지 - 다른지시자에의해서그지시자의효력이없어질때까지 전처리기는 C 를알지못함 A Book on C, 4ed. 8-2
지정된파일을읽어드림 #include filename #include <filename> #include #include 에명시되는파일의내용은제한이없음 또한그파일은전처리기에의해다시확장되어야하 는또다른전처리지시자를포함할수도있음 A Book on C, 4ed. 8-3
#include #include filename - 이행은 filename 파일의사본으로대치됨 - filename 파일은먼저현재디렉토리에서검색하고, 거기에없다면시스템이정의한디렉토리에서검색함 #include <filename> - 이것은시스템이정의한디렉토리에서만검색함 - UNIX 시스템에서 stdio.h와 stdlib.h 같은표준헤더파일은 /usr/include에있음 - 일반적으로, 표준헤더파일이저장된장소는시스템에따라다름 A Book on C, 4ed. 8-4
#define 두가지형식 #define identifier token_string opt #define identifier(id_1,..., id_n) token_string opt 정의가길어질경우에현재행의끝에역슬래시 \ 를 삽입하면, 다음행에연결해서계속쓸수있음 A Book on C, 4ed. 8-5
#define identifier t_string opt 전처리기는문자열을제외한파일의모든 identifier 를 token_string 으로대치 예제 #define SECONDS_PER_DAY (60 * 60 * 24) - 이예제에서 token_string은 (60 * 60 * 24) 이고, 전처리기는그파일의이다음부터발견되는기호상수 SECONDS_PER_DAY 모두를 (60 * 60 * 24) 로대치함 A Book on C, 4ed. 8-6
#define identifier t_string opt #define을사용하면프로그램의명확성과이식성을높일수있음 #define PI 3.14159 #define C 299792.458 /*speed of light*/ A Book on C, 4ed. 8-7
#define identifier t_string opt 특수한상수들도기호상수로코딩될수있음 #define EOF (-1) /* typical end-of-file value */ #define MAXINT 2147483647 /* largest 4-byte integer */ A Book on C, 4ed. 8-8
#define identifier t_string opt 기호상수는불명확한상수를연상기호식별자로바꿈으로써프로그램의문서화에도움을줌 시스템에따라달라지는상수를한번에변경할수있으므로이식성을높여줌 상수의실제값을검사하는데한곳만검사하면되므로신뢰성도높여줌 A Book on C, 4ed. 8-9
구문변경 C 의구문을사용자의취향에맞게변경하는것이가능 예제 - 논리수식에서 == 대신 EQ 사용 #define EQ == - while 문을 ALGOL 형식의 while do로변환 #define do /* blank */ A Book on C, 4ed. 8-10
일반적인형태 인자를갖는매크로 #define identifier(id_1,..., id_n) token_string opt - 첫번째 identifier 와왼쪽괄호사이에는공백이없어야함 - 매개변수목록에는식별자가없거나또는여러개가올수있음 A Book on C, 4ed. 8-11
예제 인자를갖는매크로 #define SQ(x) ((x) * (x)) - SQ(7 + w) 는 ((7 + w) * (7 + w)) 로확장 - SQ(SQ(*p)) 는 ((((*p) * (*p))) * (((*p) * (*p)))) 로확장 A Book on C, 4ed. 8-12
인자를갖는매크로 유의사항 매크로를정의할때올바른평가순서를유지하기위해괄호를적절히사용해야함 부적절한괄호를사용한예 #define SQ(x) x * x : SQ(a + b) ==> a + b * a + b ((a + b) * (a + b)) #define SQ(x) (x) * (x) : 4 / SQ(2) ==> 4 / (2) * (2) ( 4 / ((2) * (2)) A Book on C, 4ed. 8-13
인자를갖는매크로 유의사항 실수할수있는또다른예제 #define SQ (x) ((x) * (x)) : SQ(7) ==> (x) ((x) * (x)) (7) #define SQ(x) ((x) * (x)); /* error */ : if (x == 2) x = SQ(y); else ++x; ==> if (x == 2) x = ((y) * (y));; else ++x; A Book on C, 4ed. 8-14
인자를갖는매크로 매크로를정의할때, 매크로몸체에매크로나함수를사용할수있음 #define min(x, y) (((x) < (y))? (x) : (y)) #define min4(a, b, c, d) min(min(a, b), min(c, d)) #define SQ(x) ((x) * (x)) #define CUBE(x) (SQ(x) * (x)) #define F_POW(x) sqrt(sqrt((cube(x))) A Book on C, 4ed. 8-15
인자를갖는매크로 #undef 는매크로정의를무효화함 #undef identifier 전처리기결과보기 cc -E file.c - 이명령을사용하면, 전처리기가작업을수행한다음에더이상의컴파일이일어나지않음 A Book on C, 4ed. 8-16
stddef.h 이헤더파일은다른곳에서공통적으로사용되는몇 가지형정의과매크로를포함하고있음 예 typedef int ptrdiff_t; /* pointer difference type */ typedef short wchar_t; /* wide character type */ typedef unsigned size_t; /* the sizeof type */ #define NULL ((void *) 0) A Book on C, 4ed. 8-17
getc() 와 putc() 함수 stdio.h 의매크로 - getc() : 파일로부터한문자를읽음 - putc() : 파일에한문자를출력 getchar() 와 putchar() 매크로 #define getchar() getc(stdin) #define putchar(c) putc((c), stdout) A Book on C, 4ed. 8-18
ctype.h 의매크로 매크로 isalpha(c) isupper(c) islower(c) isdigit(c) isalnum(c) isxdigit(c) isspace(c) ispunct(c) isprint(c) isgraph(c) iscntrl(c) isascii(c) 참값 (0이아닌값 ) 이리턴되는경우 c가문자일때 c가대문자일때 c가소문자일때 c가숫자일때 c가영문자나숫자일때 c가 16진숫자일때 c가공백문자일때 c가구두문자일때 c가인쇄가능한문자일때 c가공백이아닌인쇄가능한문자일때 c가제어문자일때 c가 ASCII 코드일때 A Book on C, 4ed. 8-19
ctype.h 의매크로 함수또는매크로 toupper(c) tolower(c) toascii(c) 리턴되는값 c가소문자이면대응되는대문자, 아니면 c c가대문자이면대응되는소문자, 아니면 c c와대응되는 ASCII 코드값 A Book on C, 4ed. 8-20
조건부컴파일 조건부컴파일을위한지시자 #if constant_integral_expression... #endif #ifdef... #endif identifier // or #if defined(identifier) #ifndef... #endif identifier A Book on C, 4ed. 8-21
조건부컴파일 코드가컴파일되기위해서는 #if 다음의상수수식이영이아닌값 ( 참 ) 을가져야함 #ifdef나 #if defined와 #endif 사이의코드가컴파일되기위해서는 identifier가이미정의되어있어야하고, 그 identifier가취소 (#undef identifier) 되지않았어야함 #ifndef와 #endif 사이의코드가컴파일되기위해서는 #ifndef 다음의 identifier가현재정의되어있지않아야함 A Book on C, 4ed. 8-22
조건부컴파일예제 1 이식성이높은코드를만들기위해사용할수있음 #if defined(hp9000) defined(sun4) &&!defined(vax)... /* machine-dependent code */ #endif A Book on C, 4ed. 8-23
조건부컴파일예제 2 디버깅을위해사용할수있음 #define DEBUG 1.... #if DEBUG debugging code #endif #define DEBUG.... #ifdef DEBUG debugging code #endif A Book on C, 4ed. 8-24
조건부컴파일예제 3 디버깅을위해사용할수있음 2 statements /* more statements */ and still more statements statements #if 0 more statements #endif and still more statements A Book on C, 4ed. 8-25
조건부컴파일예제 4 매크로이름이중복지정되는것을피하기위해사용할수있음 #include "everyting.h" #undef PIE #define PIE "I like apple."... A Book on C, 4ed. 8-26
if-else 형의구조 #if 조건부컴파일 #elif constant_integral_expression #else #endif A Book on C, 4ed. 8-27
미리정의된매크로 ANSI C 에는미리정의된다섯개의매크로가있고, 이매크로는항상사용할수있으며, 프로그래머가정의를해제할수없음 각매크로이름은두개의밑줄문자로시작해서두개의밑줄문자로끝남 미리정의된매크로 DATE FILE LINE STDC TIME 값현재날짜를포함하는문자열파일이름을포함하는문자열현재라인번호를나타내는정수 ANSI C 표준을따르는경우 0이아닌값을가짐현재시간을포함하는문자열 A Book on C, 4ed. 8-28
# 연산자 " 문자열화 " 연산자 #define message_for(a, b) \ printf(#a " and " #b ": We love you!\n") int main(void) { message_for(carole, Debra); return 0; } A Book on C, 4ed. 8-29
토큰결합연산자 ## 연산자 #define X(i) x ## i X(1) = X(2) = X(3); - 전처리기수행후의결과 : x1 = x2 = x3; A Book on C, 4ed. 8-30
assert() 매크로 수식의값이기대하고있는값인가를확인할때사용 #include <assert.h> void f(char *p, int n){... assert(p!= NULL); assert(n > 0 && n < 7):... 만일단정이실패하면, 시스템은메시지를출력하고프로그램을중단함 NDEBUG가정의되어있으면, 모든단정은무시됨 A Book on C, 4ed. 8-31
#error 조건들을강요하기위해사용 전처리기가 #error를만나면, 컴파일오류가발생하고, 이지시자다음에쓰인문자열이화면에출력됨 사용예 #if A_SIZE < B_SIZE #error "Incompatible sizes" #endif A Book on C, 4ed. 8-32
행번호 사용형태 #line integral_constant "filename" - 이것은컴파일러로하여금원시프로그램의행번호를다시매기게하여그다음행의번호가 integral_constant 가되게함 - 또한컴파일러에게현재원시파일의이름이 filename 이라고믿게함 - 파일이름이명시되지않으면, 행번호만을다시매김 - 보통행번호는프로그래머에게감추어지고, 경고나구문오류가발생될때에만나타남 A Book on C, 4ed. 8-33
대응함수 표준헤더파일에있는매개변수를갖는대부분의매크로는이와대응되는함수를표준라이브러리에가지고있음 매크로대신함수를사용하기위해서는다음과같이함 - 방법 1 - 함수사용전에다음과같은행을삽입함 #undef isalpha - 방법 2 - 다음과같이호출함 (isalpha)(c) A Book on C, 4ed. 8-34