c컴파일러는 원시프로그램을 컴파일하기 전에 전처리하는 단계를 거치게 되는데요..
이는 전처리기에 의해서 실행이되죠..
전처리기 커맨드는 아래와같습니다..
#include ... file삽입
#define ... macro정의
#undef ... macro해제
#if #ifdef #endif ... 조건컴파일
#else #elif ... 조건컴파일
#line ... 행번호 부가
#pragma ... 컴파일러에게 option사용
#error ... 전처리기 기술 오류 표시
# ... 행 무시 지령
한번쯤은 다보았을 문법입니다..
주의할점은 전처리기의 명령은 한행에 기술하는것을 원칙으로 하기때문에
한행을 초과했을시에는 \기호를 행의 맨뒤에 넣어줘야합니다..
저기호는 연결표시이기때문에 맨마지막행에서는 연결할행이없으므로 안넣어줘도 됩니다..
#include <파일명>
#include "파일명"
위의 명령은 설정된 표준디렉토리에서 해당파일을 검사하여 실행파일에 삽입합니다..
만약 ""을 사용할경우에는 현재디렉토리를 검사하여 없는경우 표준디렉토리에서 파일을 찾습니다..
#define 문자열1 문자열2
#define macro(인수) 인수를 포함한 문자열
define명령어도 우리가 많이 봐왔던것입니다.
인수는 2개를 필요로하며 2번째 예제가 자주 사용되는것입니다..
문자열치환은 일반적인 기호정수가 사용됩니다.. (예 : #define TRUE 1)
기호정수는 일반변수와 구분하기위해 대문자로 쓰는것이 관례입니다..(꼭 대문자일필요는 없습니다..)
무한루프같은것을 정의한다면 좀 편합니다..
#define loop while(1)
.
.
loop{
.
.
.
}
다음은 좀 생소한 전처리명령을 보도록하죠..
주로 rtti에서 많이 쓰입니다..
# : #다음의 매크로 인수사용시 출력가능한 문자열로 전개해석될수있다..
## : 두개의 토큰을 결합하는 연산자로 명칭을 동적으로 작성될때 사용된다..
간단한 예를 보시면 이해가 더빠를듯..
#define dataput(dt) printf(#dt "%d\n",dt);
.
.
.
dataput(abc); --> printf("abc" "%d\n",abc);와 같은효과를 가진다..
#define stmake(a,b) a##b#:
.
.
.
stmake(jmp,100) --> jmp 100:과 같은효과를 가진다..(#:에서 :이 삽입됨)
그렇다면 정의된 매크로를 해제하는 기능도있습니다..
#define SIZE 1024
.
.
.
#undef SIZE
#define SIZE 2048
물론 undef를 생략할 수도 있습니다.. 재정의는 가능하지만 자연스럽지 않기때문에 경고 메시지가 출력되는군요..
#if 정수식
실행부분1
#elif 정수식
실행부분2
.
.
.
#else
실행부분n
#endif
위의명령어는 조건이있는 컴파일입니다..
여기에서 elif와 else가 필요가없다면 생략해도 무방합니다..
그냥 if - else if - else를 생각하시면 이해가 빠릅니다..
.
.
.
#if defined 명칭
.
.
#if !defined 명칭
.
.
#endif
.
.
이것은 명칭이 정의되었는지 확인하는 매크로입니다..어떤명칭이 참일시
조건을 판정하지만 아니라면 !define이 실행되게됩니다..둘중 아무거나 써도 상관없습니다..
아래명령어 역시 정의된여부판정에 쓰이는 매크로명입니다.
.
.
.
#ifdef 명칭
.
.
#ifndef 명칭
.
.
#endif
.
.
.
다음은 행번호와 파일명재부여에 대해 알아보겠습니다..
#line 행번호 "파일명"
이것은 정의 삽입 매크로로써 _LINE_과 _FILE_의 내용을 변경합니다..
음.. 컴파일 실행중 행번호와 파일명을 지정한 번호로 변경되구 여기에서 파일명은 생략이 가능합니다..
저것은 컴파일시 파일명과 행번호가 오류메시지 출력에 나타나게 됩니다..
오류가 발생하는곳에 행번호를 삽입하면 디버깅이 편리하겠죠??
#pragma 지시자
이것은 컴파일러에게 옵션을 지시합니다..
쉽게말해 특수한기능을 사용하겠다는 정보를 컴파일러에게 알려주는 명령입니다.
여기에서 지시자는 특별하게 규정된것은 없구 각 언어개발자에 의해 규정되기때문에 메뉴얼을 참고해야 합니다..
마이크로소프트c로 예를들면 아래와같습니다..
#pragma optimize ... 최적화 옵션의 금지/허가를 한다.
#pragma title ... 원시리스트에 title를 부여한다.
#pragma wdm ... 경고메시지 출력여부를 지시한다..
다음은 마지막 매크로입니다..
#error 오류메시지
저매크로는 #if문과 같이 많이 사용되며, 컴파일시 독자적으로 오류메시지를 출력합니다..
또한 컴파일처리를 중단하기도 합니다.
#if ...
.
.
.
#else
#error 에러입니다.
#endif
저런식으로 했을때 에러가 발생됐다면 컴파일시 아래와같은 메시지가 뜹니다..
#error:에러입니다.
근데 이거 잘사용해야 되는데...
매크로에는 치명적인 부작용이 있습니다..
즉 #define사용시 주의해야할점이있는데요..예를들어
#define add(a,b) a+b
위와같이 정의했다고 칩시다.. 근데 사용할때는 아래와같이 사용했습니다..
a=add(x+10,y+20);
이것은 프로그램의도와 다른결과를 갖게됩니다..
때문에 a와b에괄호를 쳐야합니다..
#define mult(a,b) ((a)*(b))
이런식으로요 근데 여기에서 좀 의아해할부분이있습니다.
왜 이중괄호를 치는거지?? 그냥 (a)*(b)하면 안되나??
만약 이중괄호를 하지않는다면 아래식에서 의도하지 않는 결과를 맛보게 될것입니다..
a=mult(a,y)*30;
저것은 a=(x)+(y)*30; 과 같은결과를 가져옵니다.
근데 저런 이중괄호조차 안먹히는 경우가있습니다..
#define sqr(a) ((a)*(a))
a=sqr(++x);
저것은 a=((++x)*(++x))와 같은 결과입니다..
정확히 정의되지 않는 경우가 발생하므로 함수에 비해 신뢰성이 떨어집니다.
더군다나 c++에서 #define은 완전히 찬밥신세지요.. (인라인함수로인해)
물론 아주 필요없는것은아닙니다..
그냥 잘판단해서 사용하시길..
-------------------------------------------------------------------
이는 전처리기에 의해서 실행이되죠..
전처리기 커맨드는 아래와같습니다..
#include ... file삽입
#define ... macro정의
#undef ... macro해제
#if #ifdef #endif ... 조건컴파일
#else #elif ... 조건컴파일
#line ... 행번호 부가
#pragma ... 컴파일러에게 option사용
#error ... 전처리기 기술 오류 표시
# ... 행 무시 지령
한번쯤은 다보았을 문법입니다..
주의할점은 전처리기의 명령은 한행에 기술하는것을 원칙으로 하기때문에
한행을 초과했을시에는 \기호를 행의 맨뒤에 넣어줘야합니다..
저기호는 연결표시이기때문에 맨마지막행에서는 연결할행이없으므로 안넣어줘도 됩니다..
#include <파일명>
#include "파일명"
위의 명령은 설정된 표준디렉토리에서 해당파일을 검사하여 실행파일에 삽입합니다..
만약 ""을 사용할경우에는 현재디렉토리를 검사하여 없는경우 표준디렉토리에서 파일을 찾습니다..
#define 문자열1 문자열2
#define macro(인수) 인수를 포함한 문자열
define명령어도 우리가 많이 봐왔던것입니다.
인수는 2개를 필요로하며 2번째 예제가 자주 사용되는것입니다..
문자열치환은 일반적인 기호정수가 사용됩니다.. (예 : #define TRUE 1)
기호정수는 일반변수와 구분하기위해 대문자로 쓰는것이 관례입니다..(꼭 대문자일필요는 없습니다..)
무한루프같은것을 정의한다면 좀 편합니다..
#define loop while(1)
.
.
loop{
.
.
.
}
다음은 좀 생소한 전처리명령을 보도록하죠..
주로 rtti에서 많이 쓰입니다..
# : #다음의 매크로 인수사용시 출력가능한 문자열로 전개해석될수있다..
## : 두개의 토큰을 결합하는 연산자로 명칭을 동적으로 작성될때 사용된다..
간단한 예를 보시면 이해가 더빠를듯..
#define dataput(dt) printf(#dt "%d\n",dt);
.
.
.
dataput(abc); --> printf("abc" "%d\n",abc);와 같은효과를 가진다..
#define stmake(a,b) a##b#:
.
.
.
stmake(jmp,100) --> jmp 100:과 같은효과를 가진다..(#:에서 :이 삽입됨)
그렇다면 정의된 매크로를 해제하는 기능도있습니다..
#define SIZE 1024
.
.
.
#undef SIZE
#define SIZE 2048
물론 undef를 생략할 수도 있습니다.. 재정의는 가능하지만 자연스럽지 않기때문에 경고 메시지가 출력되는군요..
#if 정수식
실행부분1
#elif 정수식
실행부분2
.
.
.
#else
실행부분n
#endif
위의명령어는 조건이있는 컴파일입니다..
여기에서 elif와 else가 필요가없다면 생략해도 무방합니다..
그냥 if - else if - else를 생각하시면 이해가 빠릅니다..
.
.
.
#if defined 명칭
.
.
#if !defined 명칭
.
.
#endif
.
.
이것은 명칭이 정의되었는지 확인하는 매크로입니다..어떤명칭이 참일시
조건을 판정하지만 아니라면 !define이 실행되게됩니다..둘중 아무거나 써도 상관없습니다..
아래명령어 역시 정의된여부판정에 쓰이는 매크로명입니다.
.
.
.
#ifdef 명칭
.
.
#ifndef 명칭
.
.
#endif
.
.
.
다음은 행번호와 파일명재부여에 대해 알아보겠습니다..
#line 행번호 "파일명"
이것은 정의 삽입 매크로로써 _LINE_과 _FILE_의 내용을 변경합니다..
음.. 컴파일 실행중 행번호와 파일명을 지정한 번호로 변경되구 여기에서 파일명은 생략이 가능합니다..
저것은 컴파일시 파일명과 행번호가 오류메시지 출력에 나타나게 됩니다..
오류가 발생하는곳에 행번호를 삽입하면 디버깅이 편리하겠죠??
#pragma 지시자
이것은 컴파일러에게 옵션을 지시합니다..
쉽게말해 특수한기능을 사용하겠다는 정보를 컴파일러에게 알려주는 명령입니다.
여기에서 지시자는 특별하게 규정된것은 없구 각 언어개발자에 의해 규정되기때문에 메뉴얼을 참고해야 합니다..
마이크로소프트c로 예를들면 아래와같습니다..
#pragma optimize ... 최적화 옵션의 금지/허가를 한다.
#pragma title ... 원시리스트에 title를 부여한다.
#pragma wdm ... 경고메시지 출력여부를 지시한다..
다음은 마지막 매크로입니다..
#error 오류메시지
저매크로는 #if문과 같이 많이 사용되며, 컴파일시 독자적으로 오류메시지를 출력합니다..
또한 컴파일처리를 중단하기도 합니다.
#if ...
.
.
.
#else
#error 에러입니다.
#endif
저런식으로 했을때 에러가 발생됐다면 컴파일시 아래와같은 메시지가 뜹니다..
#error:에러입니다.
근데 이거 잘사용해야 되는데...
매크로에는 치명적인 부작용이 있습니다..
즉 #define사용시 주의해야할점이있는데요..예를들어
#define add(a,b) a+b
위와같이 정의했다고 칩시다.. 근데 사용할때는 아래와같이 사용했습니다..
a=add(x+10,y+20);
이것은 프로그램의도와 다른결과를 갖게됩니다..
때문에 a와b에괄호를 쳐야합니다..
#define mult(a,b) ((a)*(b))
이런식으로요 근데 여기에서 좀 의아해할부분이있습니다.
왜 이중괄호를 치는거지?? 그냥 (a)*(b)하면 안되나??
만약 이중괄호를 하지않는다면 아래식에서 의도하지 않는 결과를 맛보게 될것입니다..
a=mult(a,y)*30;
저것은 a=(x)+(y)*30; 과 같은결과를 가져옵니다.
근데 저런 이중괄호조차 안먹히는 경우가있습니다..
#define sqr(a) ((a)*(a))
a=sqr(++x);
저것은 a=((++x)*(++x))와 같은 결과입니다..
정확히 정의되지 않는 경우가 발생하므로 함수에 비해 신뢰성이 떨어집니다.
더군다나 c++에서 #define은 완전히 찬밥신세지요.. (인라인함수로인해)
물론 아주 필요없는것은아닙니다..
그냥 잘판단해서 사용하시길..
-------------------------------------------------------------------
'Programming > C&C++' 카테고리의 다른 글
xmalloc (0) | 2006.10.31 |
---|---|
[C]scanf의 오류 (1) | 2006.04.27 |
[C]hashing (0) | 2006.01.18 |
dirent (0) | 2006.01.03 |
[C++]파일 입출력에 관한 모든 것 (2) | 2006.01.03 |