달력

03

« 2010/03 »

  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
  •  
2008/02/29 10:19

FAQ/DoWhile0 wkoh+development2008/02/29 10:19

커널 코드를 보다보면 #define do {...} while(0) 가 종종 쓰인다. 이러한 부분이 kernelnewbies.org 에 있어서 간단히 정리해 놓는다.

  • (Dave Miller는) Empty statements의 경우 컴파일러가 warning으로 간주하기 때문에 dowhile0 블럭을 사용한다.
  • (Dave Miller는) local variables를 선언하는 basic block으로 간주할 수 있다.
  • (Ben Collins는) 이는 조건이 담긴 코드에서 보다 복잡한 메크로를 사용할 수 있도록 지원하다고 말하고 있다. 만약 몇줄로 이뤄진 하나의 매크로가 다음과 같다면...
#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);;

여기서 보이다시피 원치않게도 do_something_useful은 조건문에 속하지 않게 된다. 그래서
dowhile0를 사용하여
if (blah == 2)
do {
printf("arg is %s\n", blah);
do_something_useful(blah);
} while (0);
와 같은 형태로 만드는 것이다.
  • (Per Persson은) Muller 와 Collins가 지적한 바와 같이 block statement를 사용하길 원할때, 몇몇줄의 코드와 local variables를 선언할 수 있다고 언급했다. 그러나 일반적으로 사용할 때는 차라리 다음과 같이 사용하는 편이 더욱 직관적이겠다.
#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

그러나 이는 어떤 경우에 대해서는 정상적으로 동작하지 않는다. 다음 코드는 두개의 브랜치를 가지는 If-statement 이다.
if (x > y) exch(x,y); // Branch 1 else do_something(); // Branch 2 그러나 이는 오직 하나의 브랜치만을 갖고있는 if-statement로 해석되게 된다. 다음과 같이...
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();
블럭 뒤에 바로 나오는 semi-colone(;)이 문제가 된 것이다. 이에 대한 해결책은 역시 dowhile0를 사용하는 것이다. 그러면 블럭의 capabilities를 갖는 하나의 statement 를 사용하게 되는 것으로, 다음과 같이 해석될 것이다.
if (x > y) do { int tmp; tmp = x; x = y; y = tmp; } while(0); else do_something();
  • (Bart Trojanowski는) gcc는 dowhile0 블럭을 대체할 수 있는 Statement-Expressions를 제공하고 있다고 언급했다. 이는 위의 장점에 더욱 읽기 쉽다라는 추가적인 장점을 제공한다.
#define FOO(arg) ({         \
           typeof(arg) lcl; \
           lcl = bar(arg);  \
           lcl;             \
    }) 
Posted by wkoh