C并没有像C++类似的模板(template)可以实现泛型编程的机制。那么如何实现支持不同的类型呢?

一种常用的方法是使用void *指针。

typedef struct StackElet_
{
  void *elet;
  struct StackElet_ *next;
} StackElet;

typedef struct Stack_ 
{
  size_t size;
  StackElet *top;
} Stack;

Stack   *stackNew(void);
void    stackDel(Stack *stack);

size_t  stackSize(Stack *stack);
bool    stackEmpty(Stack *stack);

void    stackPush(Stack *stack, void *elet);
void    *stackPop(Stack *stack);

stack.h

使用void *elet可以指向任一类型的数据。

Stack *
stackNew(void)
{
  Stack *stack = calloc(1, sizeof(Stack) );
  assert(stack);
  stack->size = 0;
  stack->top  = NULL;
  return stack;
}

void 
stackDel(Stack *stack)
{
  while(stack->size > 0)
    stackPop(stack);
  free(stack);
}

size_t 
stackSize(Stack *stack)
{
  return stack->size;
}

bool 
stackEmpty(Stack *stack)
{
  return (stack->size == 0) ? true : false;
}

void 
stackPush(Stack *stack, void *elet)
{
  StackElet *stackElet = calloc(1, sizeof(StackElet) );
  assert(stackElet);

  stackElet->elet = elet;
  stackElet->next = stack->top;

  stack->top  = stackElet;
  stack->size += 1;
}

void *
stackPop(Stack *stack)
{
  StackElet *toPop;
  void *elet;

  toPop = stack->top;
  stack->top = toPop->next;
  stack->size -= 1;

  elet = toPop->elet;
  free(toPop);
  return elet;
}

stack.c

使用一个简单数据结构测试:

typedef struct Data_
{
  int i;  
} Data;

Data *dataNew(int i);
void dataDel(Data *data);
void printData(Data *data);

data.h

  Stack *stack = stackNew();
  int i;

  for(i = 0; i < 10; i++) {
    Data *data = dataNew(i);
    stackPush(stack, data);
    printf("push: i:%d\n", i);
  }

  printf("stack size:%u\n", stackSize(stack) );

  while(stackSize(stack) > 0) {
    Data *data = stackPop(stack);
    printf("pop: ");
    printData(data);
    dataDel(data);
  }
  
  stackDel(stack);

test_stack.c

测试结果:

==4247== Memcheck, a memory error detector
==4247== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4247== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==4247== Command: ./test_stack
==4247== 
push: i:0
push: i:1
push: i:2
push: i:3
push: i:4
push: i:5
push: i:6
push: i:7
push: i:8
push: i:9
stack size:10
pop: data: i:9
pop: data: i:8
pop: data: i:7
pop: data: i:6
pop: data: i:5
pop: data: i:4
pop: data: i:3
pop: data: i:2
pop: data: i:1
pop: data: i:0
==4247== 
==4247== HEAP SUMMARY:
==4247==     in use at exit: 0 bytes in 0 blocks
==4247==   total heap usage: 22 allocs, 22 frees, 1,240 bytes allocated
==4247== 
==4247== All heap blocks were freed -- no leaks are possible
==4247== 
==4247== For counts of detected and suppressed errors, rerun with: -v
==4247== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

没有内存泄漏。