2015년 5월 21일 목요일

여러 명령이 포함된 매크로 함수는 do while을 사용하자!

아래 코드를 보자


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
 
#define SWAP(x, y, t) { \
                            (t) = (x); \
                            (x) = (y); \
                            (y) = (t); }
 
int main(void){
    
    int a=10;
    int b=20;
    int tmp;
 
    printf("a : %d\n", a); // 10
    printf("b : %d\n", b); // 20
 
    SWAP(a, b, tmp);
 
    printf("a : %d\n", a); // 20
    printf("b : %d\n", b); // 10
 
    return 0;
}
 
cs


SWAP함수에서 총 3개의 명령문을 실행한다
(물론 ','를 이용하여 하나의 명령문으로 해결할 수도 있으며 비트연산자를 통해 한줄안에 처리할 수 있지만 예를들기 위해 3줄로 작성했다.)

물론 잘 실행 되는 것을 확인할 수 있다. 하지만 아래와 같이 코드를 작성했다면 약간 결과가 다를 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
#include <stdio.h>
 
#define SWAP(x, y, t) { \
                            (t) = (x); \
                            (x) = (y); \
                            (y) = (t); }
 
int main(void){
    
    int a=10;
    int b=20;
    int tmp;
 
    if (1)
        SWAP(a, b, tmp);
    else
        a=0;
        
    return 0;
}
 
cs

위와 같이 코드를 짜면 에러가 발생한다.
위 코드는 예를 위해 만든 크게 의미는 없는 코드이지만 위와 같은 구조는 우리가 흔히 쓰는 방식이다.


16번째 줄에서 문제가 발생하는데 SWAP함수를 호출하면서 ';' 이 뒤에 붙었기 때문이다.
그러므로 else문이 제대로 동작하지 못한다. (if 문의 영역에서 세미콜론으로 끝나버렸기 때문)


위와 같은 문제를 해결하기 위한 방법으로 여러 줄의 매크로 함수를 작성할 때는 do while문을 쓴다.


아래 코드를 보자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
#include <stdio.h>
 
#define SWAP(x, y, t) do{ \
                            (t) = (x); \
                            (x) = (y); \
                            (y) = (t); } while(0)
 
int main(void){
    
    int a=10;
    int b=20;
    int tmp;
 
    if (1)
        SWAP(a, b, tmp);
    else
        a=0;
        
    return 0;
}
 
cs


모두 동일하지만 SWAP 함수를 선언하는 부분을 do { } while(0) 으로 싸고있다.
위 코드는 에러가 발생하지 않고 정상적으로 잘 동작할 것이다.


16번째 줄에서 SWAP를 호출하며 ';' 를 뒤에 붙였지만 do { } while(0) 뒤에 세미콜론이 붙은 형태로 치환되면서 아무런 문제없이 else문으로 넘어갈 것이다.


여러 줄을 사용하는 매크로 함수에서 중괄호를 이용하여 여러 명령문을 묶어주면 if else 문에서 위에서와 같은 문제가 발생할 수 있으므로 중괄호 대신 do while 문을 이용해서 여러 명령문을 묶어주자는 의미이다.


do while문은 반복문으로 동작하기 때문에 우리는 한번만 실행시키면 되므로 do { } while(0) 으로 작성을 해서 한번 실행하고 바로 탈출할 수 있도록 처리했다.


여러 명령어를 매크로 함수에 포함시킬 경우 꼭 do while문으로 묶어서 사용하자!


댓글 없음:

댓글 쓰기