디자인 패턴
프로그래밍을 하다보면 비슷한 기능을 하는 함수를 구현해야 하는 경우가 많다. 그럴때마다 전에 작성했던 코드를 참조하게 된다.
이런 경우, 프로그래밍을 작성하고 검증하는데 소요되는 시간을 줄일 수 있다. 바로 이러한 장점 때문에 디자인 패턴이라는 개념이 나오게 되지 않았나 생각한다.
여기서는 프로그램을 작성하다가 유용하다고 생각되는 함수를 소개할 것이다. 99.99 % C 언어가 기준이 될 것이다.
배열을 이용한 함수 호출
일반적으로 함수호출은 프로그램 루틴 중에 함수의 이름을 적어줌으로서 호출된다. 그렇다면, 어떤 경우에 배열을 이용해서 함수를 호출하는 것일까?
간단한 예를 하나 들어보겠다.
리눅스 디바이스 드라이버를 만들기 위해서는 각 디바이스마다 알아야 하는 여러가지 규칙이 있지만, 그 중에서 모든 드라이버에 공통적으로 해당되는 규칙이 있다면 그것은 바로 open(), close(), ioctl() 등의 함수가 반드시 있어야 한다는 것이다.
함수 이름은 같지만, 각 드라이버마다 루틴은 다르다. 바로 이런 경우에 배열을 이용해서 함수를 호출함으로서 해결할 수 있다.
이제 구체적인 사용 예제를 살펴보도록 하자!
typedef struct _tag_DB_OP
{
int type;
int (*insert)(int value);
int (*delete)(int value);
int (*print)(int value);
}DB_OP_T;
...
int db_btree_insert(int value);
int db_btree_delete(int value);
int db_btree_print(int value);
int db_dummy_insert(int value);
int db_dummy_delete(int value);
int db_dummy_print(int value);
...
static DB_OP_T btree_op =
{
insert:db_btree_insert,
delete:db_btree_delete,
print:db_btree_print,
};
static DB_OP_T dummy_op =
{
insert:db_dummy_insert,
delete:db_dummy_delete,
print:db_dummy_print,
};
static DB_OP_T * db_ops[DB_MAX] =
{
&btree_op, /* 0 */
&dummy_op, /* 1 */
};
...
int main(void)
{
DB_OP_T * set_db;
set_db = (DB_OP_T *)malloc(sizeof(DB_OP_T));
set_db->type = db_type; // 0 또는 1 할당에 따라 호출되는 함수가 다름(btree_* 또는 dummy_*)
memcpy((void *)set_db,(void *)db_ops[set_db->type],sizeof(DB_OP_T));
set_db->insert(5); // db_btree_insert 함수 호출
...
아래 예제의 경우, type 변수값에 따라 'set_db→insert' 시에 호출되는 함수가 달라진다.