프로그래밍

c언어/c++ do while(0)

업글 2020. 12. 21. 23:51

안녕하세요 업글입니다! 이번 포스팅에서는 do while(0)에 대해서 설명드리겠습니다.

 

do while문에 대해서 모르시는 분은 아래의 포스팅을 먼저 읽어보시는 것을 추천드립니다.

2020/12/18 - [분류 전체보기] - c언어/c++ do while문

 

c언어/c++ do while문

안녕하세요 업글입니다. 이번 포스팅에서는 do while문에 대해서 설명드리겠습니다. do while문에 대한 설명 while문에 대해서 잘 모르시는 분은 지난번 포스팅한 while문에 대해서 먼저 읽어보시는 것

elevate-yourself.tistory.com

do while(0)에 대한 설명

do while(0)는 조건이 무조건 거짓이기 때문에 해당하는 코드를 반복하지 않고 1회만 수행하게 됩니다. 이렇게 되면 do while(0)를 사용하지 않고 일반적으로 코드를 작성하는 것과 동일한 결과를 출력하게 됩니다. 그런데 왜 do while(0)를 사용하는 것일까요? 제가 생각했을 때는 2가지 경우가 있습니다. 첫번째로는 코드의 가독성, 두번째는 매크로 함수 구현입니다. 하나씩 상세하게 설명드리도록 하겠습니다.

코드의 가독성

순차적으로 정상임을 확인 해야 하는 경우를 예시로 설명 드리겠습니다.

파일을 3개 open하는 코드를 예시로 들겠습니다. 설명을 위하여 약간 억지(?)인 것 같기도 합니다만 아래와 같은 경우의 정상인지 비정상인지 확인하는 코드를 작성하는 경우는 꽤나 많다고 생각합니다.

#include <stdio.h>
#include <stdint.h>

#define FILE_NUM (3)
#define NORMAL (-1)

int main()
{
	FILE* fp[FILE_NUM];
	uint32_t errorFile = NORMAL;

	fp[0] = fopen("file0.txt", "r");

	if (fp[0] != NULL) {
		fp[1] = fopen("file1.txt", "r");

		if (fp[1] != NULL) {
			fp[2] = fopen("file2.txt", "r");

			if (fp[2] != NULL) {
				// 로직
			}
			else {
				errorFile = 2;
			}
		}
		else {
			errorFile = 1;
		}
	}
	else {
		errorFile = 0;
	}

	printf("errorFile = %d", errorFile);

	return 0;
}

0번 파일이 정상적으로 open되었을 때 1번 파일을 open하고 1번 파일이 정상적으로 open되었을 때 2번 파일을 open하고 2번 파일이 정상적으로 open되었을 때 어떠한 로직을 실행하는 코드입니다. if문 안에 if문이 있고 또 if문이 있어서 코드의 가독성이 떨어지는 편입니다.

 

이러한 경우 do while(0)과 break문을 사용하여 깔끔하게 표현할 수 있습니다.

#include <stdio.h>
#include <stdint.h>

#define FILE_NUM (3)
#define NORMAL (-1)

int main()
{
	FILE* fp[FILE_NUM];
	uint32_t errorFile = NORMAL;

	do {
		fp[0] = fopen("file0.txt", "r");

		if (fp[0] == NULL) {
			errorFile = 0;
			break;
		}

		fp[1] = fopen("file1.txt", "r");

		if (fp[1] == NULL) {
			errorFile = 1;
			break;
		}

		fp[2] = fopen("file2.txt", "r");

		if (fp[2] == NULL) {
			errorFile = 2;
			break;
		}
	} while (0);

	// 로직

	printf("errorFile = %d", errorFile);

	return 0;
}

위의 코드와 동일한 동작을 하게 되지만 if문이 중첩되지 않기 때문에 코드의 가독성이 좋아지게 됩니다. 또한 do while(0) 내부에서만 사용되는 변수가 있는 경우 do while(0) 내부에서 변수를 선언하여 사용함으로써 코드를 보다 깔끔하게 작성할 수 있습니다. 이러한 경우에 do while(0)를 사용하는 것을 추천드립니다.

매크로 함수 구현

저는 오픈소스에서 do while(0)를 사용하여 매크로함수를 작성하는 것을 많이 봐왔습니다. 왜 매크로 함수 구현 시 do while(0)를 사용하는지 설명드리겠습니다.

#include <stdio.h>
#include <stdint.h>

#define MACRO_FUNCTION_ADD(a, b, c) printf("a=%d, b=%d, c=%d\n", a, b, c);\
									c = a + b;\
									printf("c = %d\n", c)

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (0)
		MACRO_FUNCTION_ADD(a, b, c);
	

	return 0;
}

위와 같이 구현했을 때 전처리기 결과는 아래와 같이 되게 됩니다. 이는 코드가 의도한 바와 다르게 동작하게 됩니다.

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (0)
		printf("a=%d, b=%d, c=%d\n", a, b, c);
		c = a + b;
		printf("c = %d\n", c);
	

	return 0;
}

결과

의도한 바는 if 조건이 참인 경우 printf("a=%d, b=%d, c=%d\n", a, b, c) / c = a+b / printf("c = %d\n", c) 3줄의 코드를 실행하고 if 조건이 거짓인 경우 모든 줄의 코드가 실행되지 않아야합니다. 그러나 if 조건이 참인 경우에는 의도한 바와 같이 동작하지만 if 조건이 거짓인 경우 c = a+b / printf("c = %d\n", c) 2줄의 코드만 실행하게되어 의도한 바와 다르게 코드가 실행되게 됩니다.

 

또한, 아래의 코드와 같이 else가 있는 경우 컴파일러 에러가 발생하게 됩니다.

#include <stdio.h>
#include <stdint.h>

#define MACRO_FUNCTION_ADD(a, b, c) printf("a=%d, b=%d, c=%d\n", a, b, c);\
									c = a + b;\
									printf("c = %d\n", c)

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (0)
		MACRO_FUNCTION_ADD(a, b, c);
	else
		printf("else\n");

	return 0;
}

그러면 아래와 같이 { }를 추가하여 코드를 수정한 후 실행 해보도록 하겠습니다.

#include <stdio.h>
#include <stdint.h>

#define MACRO_FUNCTION_ADD(a, b, c)	{\
										printf("a=%d, b=%d, c=%d\n", a, b, c); \
										c = a + b; \
                                        printf("c = %d\n", c); \
									}

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (1)
		MACRO_FUNCTION_ADD(a, b, c);
		
	return 0;
}

if(1) 결과
if(0) 결과

if가 참, 거짓인 경우 모두 의도한 바와 같이 동작하게 됩니다.

 

그러나 아래의 코드는 위에서 컴파일러 에러가 발생하는 코드와 같이 동일하게 에러가 발생하게 됩니다.

#include <stdio.h>
#include <stdint.h>

#define MACRO_FUNCTION_ADD(a, b, c)	{\
										printf("a=%d, b=%d, c=%d\n", a, b, c); \
										c = a + b; \
                                        printf("c = %d\n", c); \
									}

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (1)
		MACRO_FUNCTION_ADD(a, b, c);
	else
		printf("else\n");
    
	return 0;
}

 

do while(0)를 사용하여 매크로 함수를 작성한 후 코드를 실행해보도록 하겠습니다.

#include <stdio.h>
#include <stdint.h>

#define MACRO_FUNCTION_ADD(a, b, c) do{\
										printf("a=%d, b=%d, c=%d\n", a, b, c);\
										c = a + b;\
										printf("c = %d\n", c);\
									}while(0)

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (1)
		MACRO_FUNCTION_ADD(a, b, c);
		
	return 0;
}

if(1) 결과
if(0) 결과

if가 참, 거짓인 경우 모두 의도한 바와 같이 동작하게 됩니다.

 

또한, do while(0)를 사용하면 아래의 코드에서 컴파일러 에러가 발생하지 않고 코드가 의도한 대로 동작하게 됩니다.

#include <stdio.h>
#include <stdint.h>

#define MACRO_FUNCTION_ADD(a, b, c) do{\
										printf("a=%d, b=%d, c=%d\n", a, b, c);\
										c = a + b;\
										printf("c = %d\n", c);\
									}while(0)

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (1)
		MACRO_FUNCTION_ADD(a, b, c);
	else
		printf("else\n");
        
	return 0;
}

if(1) 결과
if(0) 결과

 

do while(0)를 제외하고 위의 2가지 경우에서도 아래의 코드와 같이 if와 else에 { }만 추가해준다면 코드가 의도한 대로 동작되고 컴파일 에러가 발생하지 않습니다. 

#define MACRO_FUNCTION_ADD(a, b, c)		printf("a=%d, b=%d, c=%d\n", a, b, c); \
										c = a + b; \
										printf("c = %d\n", c)

//#define MACRO_FUNCTION_ADD(a, b, c)		{\
										printf("a=%d, b=%d, c=%d\n", a, b, c); \
										c = a + b; \
										printf("c = %d\n", c); \
										}

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (0) {
		MACRO_FUNCTION_ADD(a, b, c);
	}
	else{
		printf("else\n");
	}
		
	return 0;
}

그러나 사용자에 따라서 if에 코드가 한줄만 실행되는 경우 { }를 생략하고 작성하는 경우가 있기 때문에 매크로 함수를 작성하실 때는 do while(0)를 필수적으로 사용하는 것을 추천드립니다.

 

또한, if문 사용 시 코드가 한줄만 실행되더라도 { }를 사용하여 코드를 작성하시는 것을 추천드립니다. 위와 같은 상황을 미리 방지하기 위함입니다. 코드가 간결할 때는 이러한 문제를 쉽게 찾을 수 있지만 코드가 복잡해지면 많은 시간을 낭비할수도 있기 때문입니다.

 

이상 do while(0)에 대한 설명을 마치도록 하겠습니다!

'프로그래밍' 카테고리의 다른 글

[c언어] 링크드리스트(Linked List)  (0) 2021.01.13
[c언어] 큐(Queue)  (0) 2021.01.01
c언어/c++ do while문  (2) 2020.12.18
c언어/c++ while문  (0) 2020.12.17
c언어/c++ if 조건문  (0) 2020.12.17