Programming/C&C++

[퍼옴]전처리기

다자매_아빠 2006. 3. 9. 01:50
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은 완전히 찬밥신세지요.. (인라인함수로인해)
물론 아주 필요없는것은아닙니다..
그냥 잘판단해서 사용하시길..

-------------------------------------------------------------------

'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