如前一篇文章提到的环形队列,如果我的数据类型是u16,u8,u32,结构体,那么是不是每一种数据类型都定义一个环形队列呢,答案是肯定的,但是这个过程可以交由编译器处理,看下面的代码
#define DEFINE_QUEUE_TYPE(NAME, TYPE, SIZE) \
typedef struct { \
TYPE data[SIZE]; \
int front; \
int rear; \
int size; \
int max_size; \
} NAME##_queue; \
\
void NAME##_queue_init(NAME##_queue *queue) { \
queue->front = 0; \
queue->rear = -1; \
queue->size = 0; \
queue->max_size = SIZE; \
} \
\
bool NAME##_queue_is_empty(NAME##_queue *queue) { \
return queue->size == 0; \
} \
\
bool NAME##_queue_is_full(NAME##_queue *queue) { \
return queue->size == queue->max_size; \
} \
\
bool NAME##_queue_push(NAME##_queue *queue, TYPE value) { \
if (NAME##_queue_is_full(queue)) { \
return false; \
} \
queue->rear = (queue->rear + 1) % queue->max_size; \
queue->data[queue->rear] = value; \
queue->size++; \
return true; \
} \
bool NAME##_queue_pop(NAME##_queue *queue) { \
if (NAME##_queue_is_empty(queue)) { \
return false; \
} \
queue->front = (queue->front + 1) % queue->max_size; \
queue->size--; \
return true; \
} \
bool NAME##_queue_front(NAME##_queue *queue, TYPE *value) { \
if (NAME##_queue_is_empty(queue)) { \
return false; \
} \
*value = queue->data[queue->front]; \
return true; \
}
是需要传入适当的宏参数,就可以使用对应数据类型的 队列,比如
DEFINE_QUEUE_TYPE(u16, uint16_t, TEST_QUUE_SIZE)
static u16_queue test_queue;
上面的第一行,定义了一个名字为u16_queue的结构体,数据类型为uint16_t,应该如何使用呢
u16_queue_init(&test_queue);
u16_queue_push(&test_queue, TEST_NUMBER1);
u16_queue_front(&test_queue, &tmp);
u16_queue_pop(&test_queue);
像这样带上名字前缀使用就可以啦,如果像换成其他的数据类型那么重新调用一个宏就可以,像这样
DEFINE_QUEUE_TYPE(u32, uint32_t, TEST_QUUE_SIZE)
static u32_queue test_queue;
是不是很方便
同理其他的数据结构也可以这样操作,如大小堆,hash表等等