가독성 씹이어서 복사 붙여넣기 했다 ㅇㅅㅇ


1. void *



2. cast 연산자



3. va_list



4. _Generic



으로 수준 높은 다형성과 오버로딩을 달성할 수 있습니다.



void * 을 사용하지 않으면 각각의 타입에 따라서 각각의 함수를 일일이 만들어야 되는데

void c_queue_enqueue_intp   (CQueue *q, int *i)
void c_queue_enqueue_int    (CQueue *q, int number)
void c_queue_enqueue_str    (CQueue *q, char *str)
void c_queue_enqueue_struct (CQueue *q, struct MyType *)


void * 을 활용하면 void c_queue_enqueue (CQueue *q, void *) 함수 하나면
떡을 칩니다.

다음은 oop 로 구현한 CQueue 입니다.

inline static void *c_mem (void *mem, const char *str)
{
  if (mem)
    return mem;

  perror (str);
  abort ();
}

void *c_malloc (size_t size)
{
  return c_mem (malloc (size), __PRETTY_FUNCTION__);
}

void *c_calloc (size_t number, size_t size)
{
  return c_mem (calloc (number, size), __PRETTY_FUNCTION__);
}


typedef void (* CFreeFunc)    (void *data);


typedef struct _CNode  CNode;
struct _CNode {
  CNode *next;
  void  *data;
};


typedef struct _CQueue  CQueue;
struct _CQueue {
  CNode     *front;
  CNode     *back;
  unsigned   count;
  CFreeFunc  free_func;
};


CQueue *c_queue_new (CFreeFunc free_func)
{
  CQueue *q;

  q = c_calloc (1, sizeof (CQueue));
  q->free_func = free_func;

  return q;
}

void c_queue_free (CQueue *q)
{
  CNode *p = q->front;

  while (p)
  {
    if (q->free_func && p->data)
      q->free_func (p->data);

    CNode *next = p->next;
    free (p);
    p = next;
  }

  free (q);
}

void c_queue_enqueue (CQueue *q, void *data)
{
  CNode *node = c_malloc (sizeof (CNode));
  node->next = NULL;
  node->data = data;

  if (!q->count)
    q->front = node;
  else
    q->back->next = node;

  q->back = node;
  q->count++;
}

void *c_queue_dequeue (CQueue *q)
{
  if (!q->count)
    return NULL;

  CNode *node;
  void  *data;

  node = q->front;
  data = node->data;

  q->front = q->front->next;
  q->count--;

  free (node);

  return data;
}

bool c_queue_is_empty (CQueue *q)
{
  if (!q->count)
    return true;

  return false;
}

bool c_queue_remove (CQueue *q)
{
  if (!q->count)
    return false;

  CNode *node;

  node     = q->front;
  q->front = q->front->next;
  q->count--;

  if (q->free_func)
    q->free_func (node->data);

  free (node);

  return true;
}

void *c_queue_peek (CQueue *q, unsigned i)
{
  if (!q->count)
    return NULL;

  CNode *p;

  for (p = q->front; i > 0 && p; i--)
    p = p->next;

  return p->data;
}