학습자료(~2017)/C,C++

[C] 디버그용 매크로 - 매크로 가변인자사용

단세포소년 2012. 3. 15. 11:03
반응형

디버그용으로 printf 를 쓸때가 매우 많다. 디버그 목적으로 무분별하게 printf 를 추가했지만 릴리즈하기전 printf를 지우는 일은
많은 노동력이 든다. 이 노동을 매크로를 이용해서 릴리즈할때는 디버그 목적으로 추가된 printf를 없애는 방법이다.


#if defined DEBUG

#define TRACE(fmt,...) printf(fmt,__VA_ARGS__)

#define TRACE(fmt,...) printf(fmt,##__VA_ARGS__) 

#else

#define TRACE(fmt,...)

#endif


키포인트: 
#define TRACE(fmt,...) printf(fmt,__VA_ARGS__)  이렇게만 쓸경우 TRACE("test") 와 같이 인자가 하나일때는 오류가 난다.

#define TRACE(fmt,...) printf(fmt,##__VA_ARGS__)  이렇게 ## 토큰 분할 문자를 써야 TRACE("test") 나 
TRACE("test %s","test") 등 인자가 하나일때 그 이상일때도 정상적으로 동작한다.




설명 : 가변인자를 사용하는 함수와 매우 동일한 형태의 구현이다. 매크로에서 가변 인자는 가변함수와 마찬가지로 ... 이다.
가변함수에서는 va_list, va_start(), va_arg(), va_end() 로 가변인자를 처리했다. 하지만 매크로 에서는 __VA_ARGS__ 라는 예약어(?)가 이를 처리해 준다.

리눅스와 윈도우에서 테스트 결과 잘 돌아간다.

리눅스 gcc의 경우 가변매크로에서

#define TRACE(fmt,args...) printf(fmt,args)

의 형태도 동작했지만 visual studio 에서는 컴파일조차 하지 못했다. 따라서 __VA_ARGS__ 를 이용하자.



혹시나 해서 이런 응용 방법도 생각했다. 코딩을 하다보면 printf 같이 단일적인게 아닌 블럭({}) 단위로 디버그 목적의 코드를 작성해야 할 때가 있다.
예를 들어
#if define DEBUG
double avg = sum/total;
printf("%lf",avg);
#endif
이와 같이 디버그 목적으로 한줄이상의 코드가 들어갈때가 있다. (다들 이해하셨을거라 믿는다..)

이때는

#define DEBUGBLOCK(...) do{ __VA_ARGS__ }while(0);

이렇게 정의하고 사용시

void main()
{

  DEBUGBLOCK( 
     char *str = "디버그 목적임";
     printf("%s",str);
     
   )
}

위와 같이 사용하면 된다. 왠지 안될거 같은 코드 같다는 생각들을 할텐데.. 나도 아이디어는 떠올랐는데 긴가민가해서 테스트 결과 동작햇다.


ps : 말이 참.. 두서가 없다..



반응형