[펌] 매크로 마법 (Macro)
매크로는 C와 C++에서 제공되는 꽁수같은 기능이라고 할 수 있습니다.
꽁수같다라고 한 이유가 매크로는 사용자의 편의와 동시에 많은 위험성을 초래하기 때문이죠.
그래서, 대부분의 서적에서는 매크로의 사용을 자제하고 인라인(inline)과 상수형(const)을 더 지향하기도 합니다.
하지만, 이는 단순히 매크로의 위험성 때문이며 그 위험성의 간단한 예를 들자면,
#define POW( A ) A * A // 정의했을 경우 ... POW( 10 + 10 ) // 사용자의 의도는 20 * 20 입니다. 하지만 결과는, 10 + 10 * 10 + 10 //10 + 100 + 10 = 120 이죠. |
또한, 상수형 같은 경우는 디버깅이 불가능하다는 점도 있죠. 최근에 좋은 개발 툴은 매크로 변수를 추적도 가능하다고 합니다만... 비주얼 스튜디오 2008에서도 아직 안되더군요. :|
어쨌든, 그런 위험성을 제거할 수 있고 개발자 편의로 매크로를 마음껏 사용할 수 있다면, 구지 매크로를 사용을 자제할 필요가 없다고 봅니다.
결론은, 매크로의 사용여부는 개발자 자신에게 넘기도록 하겠고, 오늘은 매크로의 비법들에 대해서 한번 살펴보도록 하겠습니다.
매크로 사용여부는 다 알고 계신다고 가정하고, 사용 설명은 따로 하지 않겠습니다. 간단한 예를 보면 쉽게 이해가 될 겁니다.
#1) 열거형을 문자열로
#define CaseEnum( A ) case( A ) : LogMsgToFile( #A )
switch( msg ) { CaseEnum( MSG_One ); ... break; CaseEnum( Msg_Two ); ... break; default: ... break; }
/*************컴파일 전처리가 끝나면, 위의 소스는 다음과 같이 대체 됩니다.***********************/
switch( msg ) { case( MSG_One ): LogMsgToFile( "MSG_One" ); ... break; case( MSG_Two ): LogMsgToFile( "MSG_Two" ); ... break; default: ... break; } |
#2) 두 인자를 하나의 값으로 합치기
#define CAT( A, B ) A ## B
value = CAT( 1, 2 );
/*************컴파일 전처리가 끝나면, 위의 소스는 다음과 같이 대체 됩니다.***********************/
value = 12; |
#3) 표준 assert에 의미있는 메세지 추가하기
#define ASSERT_MSG( A, B ) assert( a && b )
ASSERT_MSG( time > 0, "time must be bigger than zero" );
/*************컴파일 전처리가 끝나면, 위의 소스는 다음과 같이 대체 됩니다.***********************/
assert( time > 0 && "time must be bigger than zero" );
//사용에 있어서 큰 차이는 없지만 매크로가 더 사용자 직관적이지 않나요? |
#4) 컴파일 시점의 assert
//애초에 제한 조건에 벗어나면 컴파일 오류를 발생 시킵니다. #define CASSERT( A ) typedef char __C_ASSERT__[ (A) ? 1: -1 ]
CASSERT( sizeof( MyEnum ) == sizeof( unsigned int ) );
/*************컴파일 전처리가 끝나면, 위의 소스는 다음과 같이 대체 됩니다.***********************/
//만약 MyEnum의 크기가 16이라고 가정했을 때, typedef char __C_ASSERT__[ ( 16 == 4 ) ? 1: -1 ]
16 == 4는 거짓이며 따라서 __C_ASSERT[ -1 ] 이라는 형을 정의하려고 합니다. 하지만, -1의 크기의 배열 정의는 컴파일러 입장에서 불가능하기 때문에 잡아낼 수 있죠. |
#5) 배열의 원소를 구하기
//자바 같은 경우는 배열의 원소 갯수를 알 수 있지만 C/C++ 에서는 기본적으로 제공되진 않습니다. #define NUM_ELEMENT( A ) ( sizeof( A ) / sizeof( ( A[ 0 ] ) )
int a[ 10 ] int nElement = NUM_ELEMENT( a );
/*************컴파일 전처리가 끝나면, 위의 소스는 다음과 같이 대체 됩니다.***********************/
int a[ 10 ] int nElement = 40 / 4; |
#6) __LINE__을 문자열로
// 기본적으로 정의되어 있는 유용한 매크로들 입니다. __LINE__ // 컴파일 시점의 행 번호를 의미하는 정수 __FILE__ // 컴파일 되는 파일 이름을 담은 문자열 __DATE__ // 컴파일 될 때의 날짜를 담은 문자열 __TIME__ // 컴파일 될 때의 시간을 담은 문자열
//이들을 디버깅 시 유용히 활용할 수 있습니다. #define TO_MSG( X ) #X
#define __FILELINE__ __FILE__" ( " TO_MSG(__LINE__) " ) " //VC++에서는 안될 수도 있음
/*************컴파일 시 다음과 같이 출력됩니다.***********************/ c:\project\main.cpp ( 105 ) |
-참고 : Game Programming Gems 3 ( 정보문화사 )-
[출처] 매크로 마법 (Macro)|작성자 Hermet
'Tip & Tech' 카테고리의 다른 글
[펌] float -> int 형변환 정리 (2) | 2011.06.08 |
---|---|
[펌] 기업에서까지 완전 무료 프로그램 - 진정한 FREE!! (0) | 2011.06.08 |
[펌] !!a (0) | 2011.06.08 |
[펌] C Runtime 환경의 메모리 릭 잡는 방법 ( Memory Leak ) (0) | 2011.06.08 |
[펌] 비주얼 스튜디오 _CrtDumpMemoryLeaks() 을 이용한 메모리 누수 탐지법 (0) | 2011.06.08 |