"C 함수에서 2개의 return 문을 사용하게 제약한 코딩 스타일" 얘기한 함수 구조를 갖추기 위해서 예외처리 관련 매크로를 사용하고 있다.
이 예외처리 매크로는 goto 문을 이용하여 만들어 졌다. C로 구현된 매크로들을 Google에서 검색해보면 setjmp(), longjmp() 같은 것을 이용한 것들도 보이나, C 언어에서 제공되는 goto 만으로 만들어 사용하는 것이 이해하기 쉽고, 다양한 환경에서 무난하게 돌아가는 장점이 있다.
회사에서 사용하는 것보다 좀더 단순화시켜서 비슷하게 만들어 보겠다. C++이나 Java에서 사용하는 try { } catch { } 같은 스타일은 아니고, 크게 예외 판단 매크로들, 예외를 받는 매크로들로 구성이 된다.
직접 보는게 제일 이해가 빠를 것이다. 다음 프로그램은 "hello.txt"라는 파일에 "hello world"를 출력하는 프로그램이다.
[code c]/*
* http://blog2.thewhiterock.net/
*/
#include <stdio.h>
#include <errno.h>
#include "exception.h"
int main(int argc, char **argv)
{
FILE *fp = NULL;
int result = 0;
fp = fopen("hello.txt", "w");
EXCEPTION_TEST_RAISE(fp == NULL, LABEL_OPEN_FAIL);
result = fprintf(fp, "hello world\n");
EXCEPTION_TEST_RAISE(result < 0, LABEL_WRITE_FAIL);
result = fclose(fp);
EXCEPTION_TEST_RAISE(result != 0, LABEL_CLOSE_FAIL);
return 0;
EXCEPTION(LABEL_OPEN_FAIL)
{
(void)printf("Fail to open file 'hello.txt' ( %d )\n", errno);
}
EXCEPTION(LABEL_WRITE_FAIL)
{
(void)printf("Fail to write file 'hello.txt' ( %d )\n", errno);
}
EXCEPTION(LABEL_CLOSE_FAIL)
{
(void)printf("Fail to close file 'hello.txt' ( %d )\n", errno);
}
EXCEPTION_END;
return -1;
}[/code]
예외를 검사하는 EXCEPTION_TEST_RAISE() 매크로와 예외를 받는 EXCEPTION(), EXCEPTION_END 매크로들이 보인다. main() 함수의 구조를 보면 상단에는 주요 로직이 위치해 있고, 하단에는 예외 처리 로직이 위치한 형태를 가진다.
이 매크들이 구현된 것 또한 소스 코드를 직접 보는 것이 이해가 빠를 것이다. 다음은 exception.h 소스 이다.
[code c]/*
* http://blog2.thewhiterock.net/
*/
#ifndef __EXCEPTION_H__
#define __EXCEPTION_H__
#define EXCEPTION(label_name) \
goto EXCEPTION_END_LABEL; \
label_name :
#define EXCEPTION_END \
EXCEPTION_END_LABEL: \
do \
{ \
} while (0)
#define EXCEPTION_TEST(expression) \
do \
{ \
if (expression) \
{ \
goto EXCEPTION_END_LABEL; \
} \
else \
{ \
} \
} while (0)
#define EXCEPTION_TEST_RAISE(expression, label_name) \
do \
{ \
if (expression) \
{ \
goto label_name; \
} \
else \
{ \
} \
} while(0)
#define EXCEPTION_RAISE(label_name) \
do \
{ \
goto label_name; \
} while(0)
#endif /* __EXCEPTION_H__ */[/code]