Create TOC

2003년 5월 15일

매크로 선언시 do { ... } while(0)을 사용하면 좋은 이유

원문

  • 매크로 안에서 지역 변수를 선언할 수 있다.
  • 복잡한 매크로를 만들 수 있다. 예를 들어 아래와 같이 매크로를 선언하고:

#define FOO(x) \
	printf("arg is %s\n", x); \
	do_something_useful(x);

아래와 같이 사용하면:

if (blah == 2)
	FOO(blah);

이렇게 해석된다:

if (blah == 2)
	printf("arg is %s\n", blah);
	do_something_useful(blah);;

의도한 바와는 다르게 base == 2 일때 do_something_useful(blash) 는 실행되지 않는다. 이 매크로를 do{...}while(0) 을 사용해서 만들었다면 아래와 같은 코드를 얻을 수 있다:

if (blah == 2)
	do {
		printf("arg is %s\n", blah);
		do_something_useful(blah);
	} while (0);

매크로를 단지 블럭({...}) 으로만 묶을 경우 복잡한 매크로 선언이나 지역 변수 사용은 가능하나 한가지 문제가 생긴다. 아래 예를 들어:

#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

이 매크로를 if 구절에 사용하면:

if(x>y)
	exch(x,y);          // Branch 1
else
	do_something();     // Branch 2

해석하면 아래와 같은 코드가 된다:

if(x>y) {                    // Single-branch if-statement!!!
	int tmp;                 // The one and only branch consists
	tmp = x;                 // of the block.
	x = y;
	y = tmp;
}
;                            // empty statement
else                         // ERROR!!! "parse error before else"
	do_something();

세미콜론(;) 으로 인해서 if 구절이 완료가되고 그 다음 else 구절은 에러구문이 된다.

이런 문제를 해결하기 위해서 매크로를 do{...}while(0) 로 묶는다. 이럴경우 컴파일러는 코드를 아래와 같이 해석한다:

if(x>y)
	do {
		int tmp;
		tmp = x;
		x = y;
		y = tmp;
	} while(0);
else
	do_something();