typedef의 활용과 함수포인터

C언어에서 typedef 는 새로운 타입(type)을 만드는 키워드입니다. 예를 들어 bool 타입은 true, false를 가지고 있는 기본적인 타입인데, C언어에는 없습니다.

 

typedef를 통해 아래와 같이 간단하게 bool타입을 만들 수 있습니다.

typedef enum
{
  false = 0,
  true = 1
}bool;
 

그리고 아래와 같이 코딩 할 수 있습니다.

bool isRegistered = false;

if(isRegistered == true)
{
  printf("It is registered!");
}
 

좀 더 활용해 보겠습니다.

typedef struct
{
  uint8_t D0;
  uint8_t D1;
  uint8_t D2;
  uint8_t D3;
}digit_t;

 

새로운 digit_t라는 타입을 만들었습니다. 다음과 같이 사용할 수 있습니다.

digit_t speed;

speed.D0 = 0;
speed.D1 = 0;
speed.D2 = 0;
speed.D3 = 0;
 

함수 포인터는 함수를 가르키는 포인터입니다. 코드는 보통 메모리, 루프 그리고 함수로 이루어져 있고, 함수는 쉽게 말해 분기라고 할 수 있으니 함수도 코드 메모리 영역의 주소를 가지고 있습니다. 우리는 그 주소를 가르키는 포인터도 동적으로 만들어 사용할 수 있습니다.

 

아래 함수포인터 타입 선언 예제를 보겠습니다.

//Handle : return parameter
//getHandleFunc : 함수명
//instance : parameter 타입은 void 포인터형
typedef Handle (*getHandleFunc)(void* instance);
 

좀 헷갈릴지도 모르지만 자꾸 접하다 보면 익숙해집니다. 위 예제에서 return parameter인 Handle은 C에서는 실제 존재하지 않는 타입이며 이 또한 typedef로 만들어진 새로운 타입입니다.

 

위의 함수 포인터 선언은 다음과 같이 하면 됩니다.

getHandleFunc getHandle;
 

여기서 getHandle은 함수 포인터입니다. 실제 assign을 해주지 않고 사용하면 에러가 발생합니다. 자바에서 nullpointer 같은 에러가 발생할 것입니다. 다음과 같이 assign 할 수 있습니다.

typedef Handle (*getHandleFunc)(void* instance);

getHandleFunc getHandle;
Handle getEventHandle(void* instance);

void main(void)
{
  void *instance;
  ..
  ..
  getHandle = getEventHandle; //assign
  getHandle(instance);        //실제로는 getEventHandle 실행
}

Handle getEventHandle(void* instance)
{
  //Implemented
}
 

이러한 방식으로 코딩하는 것이 왜 중요한지는 앞으로 나올 디자인 패턴을 보시면 이해하게 될 것입니다. 중요한 것은 typedef로 새로운 타입을 만들 수 있다는 것과 함수포인터도 typedef를 이용하면 자바와 같은 Class와 비슷한 것을 만들 수 있다는 것 정도입니다.

 

이번 포스트는 매우 중요한 내용을 포함하고 있습니다. typedef와 함수 포인터를 이해하는데 문제가 없어야 디자인패턴을 익히는데 어려움이 없을 것입니다.