ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [퍼옴]전처리기
    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
Designed by Tistory.