상세 컨텐츠

본문 제목

[Macro함수] 라이브러리 개발시 do while(0) 를 사용하는 이유

C

by 메타샤워 2023. 7. 25. 12:52

본문

우리가 흔히 아는 문법인 do while은 잘 사용하지 않은 문법입니다.

하지만 라이브러리를 개발할 시에 do while 0 문은 아주 안정한 라이브러리 개발을 위해 반드시 사용해야할 usage가 있습니다.

지금부터 그것을 소개 해볼게요~

C나 C++로 작성된 라이브러리에서 많이 볼수 있는데

라이브러리 코드 내에서 매크로 함수의 사용성은 아주 많습니다.

라이브러리안 매크로 함수와 라이브러리를 사용하는 사용자의 코드간 문제를 한번 다뤄 보겠습니다.

 

#include <stdio.h>
 
#define SWAP(X, Y, T) { T t = X; X = Y; Y = t; } 
 
int main() 
{ 
    int a = 10, b = 20; 
    if (true) 
        SWAP(a, b, int); // 별 문제 없을 것 같았지만, 여기서 문제가 생긴다!!! 
    else ; 
}

사용자가 괄호가 없는 if 문을 사용 할수 있습니다.

그 내부에서 매크로 함수를 호출 했고, 여느 때와 같이 세미콜론을 찍었습니다.

하지만 저 코드에서 컴파일 에러가 납니다. 매크로 함수를 원형대로 치환해보겠습니다.

#include <stdio.h>
 
#define SWAP(X, Y, T) { T t = X; X = Y; Y = t; } 
 
int main() 
{ 
    int a = 10, b = 20; 
    // if (true)
        // SWAP(a, b, int);
    // else// ; 
    // 위 문장들은 아래 코드로 치환된다. 
    if (true) 
    { 
        int t = a; 
        a = b; 
        b = t; 
    }; 
    else ; 
}

 

문제가 보이십니까?

if를 끝내고 else가 시작하기전에 괄호를 닫고 세미콜론이 하나 있습니다.

#include <stdio.h>
 
#define SWAP(X, Y, T) { T t = X; X = Y; Y = t; } 
 
int main() 
{ 
    int a = 10, b = 20; 
    // if (true)
    // SWAP(a, b, int);
    // else// ; 
    // if (true)
    // { int t = a; a = b; b = t; };
    // else// ; 
    // 약간 정리해보면.. 
    if (true) 
    { 
        int t = a; 
        a = b; 
        b = t; 
    } ; // <----------------- 여기!!!!!!!!!!!!!!!!! 
    else ; 
 
    // 이렇게 치환되는데.. 
    // 이게 왜 문제냐면.. 
    // if (true) 블럭이 끝나자마자 세미콜론(;)이 있기 때문입니다! 
}

사용자는 매크로함수의 이름만 보고 호출할 것이고 사용자는 충분히 괄호 없는 if를 사용할수 있습니다.

이때 빛을 발휘하는 것이 do while 0 문 입니다.

위 코드를 do while 0 문으로 바꿔 보겠습니다.

#include <stdio.h>
 

int main() 
{ 
    int a = 10, b = 20; 
    // 아래 코드에서는 문제가 발생하지 않는다! 
    if (true) 
        do { 
            int t = a; 
            a = b; 
            b = t; 
        } while (0); 
    else ; 
}

이 것을 다시 매크로 함수로 바꿔보겠습니다.

#include <stdio.h>
 
// 중괄호를 매크로 함수로 묶는 것보다... 아래처럼 do while로 정의할 것..!
// Linux kernel code를 보면 아래와 같은 구문이 상당히 많다고 합니다!
#define SWAP(X, Y, T) \
  do { \
    T t = X; X = Y; Y = t; \
  } while (0)   // <------ 마지막에 세미콜론(;)을 붙이지 않습니다!
 
int main() {
  int a = 10, b = 20;
 
  // 아래 코드에서는 문제가 발생하지 않습니다!
  if (true)
    SWAP(a, b, int);   // <------ 여기는 세미콜론(;)을 붙입니다!
  else
    ;
 
  
}

리눅스 커널의 커널 라이브러리에 위와같은 매크로 함수가 굉장히 많다고 합니다.

관련글 더보기