环形队列
代码片段
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#define MAX_MSG_SIZE 256
#define QUEUE_EMPTY -1
#define QUEUE_FULL -2
// 消息结构体
typedef struct {
long mtype; // 消息类型,Linux 消息队列中用于区分消息
char mtext[MAX_MSG_SIZE]; // 消息内容
} Message;
// 基于环形队列的消息队列结构体
typedef struct {
Message *messages; // 存储消息的环形缓冲区
int front; // 队头指针
int rear; // 队尾指针
int capacity; // 队列容量
int size; // 当前消息数量
} MessageQueue;
// 创建消息队列
MessageQueue* msg_queue_create(int capacity) {
if (capacity <= 0) {
fprintf(stderr, "Error: Capacity must be positive\n");
return NULL;
}
MessageQueue *mq = (MessageQueue*)malloc(sizeof(MessageQueue));
if (!mq) {
perror("Memory allocation failed for message queue");
return NULL;
}
mq->messages = (Message*)malloc(sizeof(Message) * capacity);
if (!mq->messages) {
perror("Memory allocation failed for messages");
free(mq);
return NULL;
}
mq->front = 0;
mq->rear = 0;
mq->capacity = capacity;
mq->size = 0;
printf("Message queue created with capacity %d\n", capacity);
return mq;
}
// 检查消息队列是否为空
bool msg_queue_is_empty(MessageQueue *mq) {
return mq->size == 0;
}
// 检查消息队列是否已满
bool msg_queue_is_full(MessageQueue *mq) {
return mq->size == mq->capacity;
}
// 发送消息(入队)
int msg_send(MessageQueue *mq, long msg_type, const char *msg_text) {
if (msg_queue_is_full(mq)) {
printf("Message queue is full. Cannot send message.\n");
return QUEUE_FULL;
}
if (strlen(msg_text) >= MAX_MSG_SIZE) {
fprintf(stderr, "Error: Message text too long (max %d characters)\n", MAX_MSG_SIZE - 1);
return -3;
}
// 构造消息
Message msg;
msg.mtype = msg_type;
strncpy(msg.mtext, msg_text, MAX_MSG_SIZE - 1);
msg.mtext[MAX_MSG_SIZE - 1] = '\0';
// 存入环形缓冲区
mq->messages[mq->rear] = msg;
mq->rear = (mq->rear + 1) % mq->capacity;
mq->size++;
printf("Message sent: [type=%ld] %s\n", msg.mtype, msg.mtext);
return 0;
}
// 接收消息(出队),按先进先出顺序,忽略消息类型(简化版)
int msg_receive(MessageQueue *mq, long *msg_type, char *msg_text, int max_len) {
if (msg_queue_is_empty(mq)) {
printf("Message queue is empty. Cannot receive message.\n");
return QUEUE_EMPTY;
}
// 从队头取出消息
Message msg = mq->messages[mq->front];
mq->front = (mq->front + 1) % mq->capacity;
mq->size--;
if (msg_type) {
*msg_type = msg.mtype;
}
if (msg_text) {
strncpy(msg_text, msg.mtext, max_len - 1);
msg_text[max_len - 1] = '\0';
}
printf("Message received: [type=%ld] %s\n", msg.mtype, msg.mtext);
return 0;
}
// 获取消息队列当前消息数量
int msg_queue_size(MessageQueue *mq) {
return mq->size;
}
// 销毁消息队列
void msg_queue_destroy(MessageQueue *mq) {
if (mq) {
free(mq->messages);
free(mq);
printf("Message queue destroyed\n");
}
}
// 打印消息队列状态
void msg_queue_print_status(MessageQueue *mq) {
printf("Message Queue Status: ");
if (msg_queue_is_empty(mq)) {
printf("Empty\n");
} else if (msg_queue_is_full(mq)) {
printf("Full\n");
} else {
printf("Partially filled\n");
}
printf(" Capacity: %d, Current size: %d\n", mq->capacity, mq->size);
printf(" Front index: %d, Rear index: %d\n", mq->front, mq->rear);
if (!msg_queue_is_empty(mq)) {
printf(" Messages in queue (from front to rear):\n");
int index = mq->front;
for (int i = 0; i < mq->size; i++) {
printf(" [%d] type=%ld, text='%s'\n",
i, mq->messages[index].mtype, mq->messages[index].mtext);
index = (index + 1) % mq->capacity;
}
}
}
// 测试函数
int main() {
printf("=== Message Queue Based on Circular Queue ===\n\n");
// 1. 创建消息队列,容量为5
MessageQueue *mq = msg_queue_create(5);
if (!mq) {
fprintf(stderr, "Failed to create message queue\n");
return 1;
}
msg_queue_print_status(mq);
printf("\n");
// 2. 发送几条消息
printf("--- Sending messages ---\n");
msg_send(mq, 1, "Hello, this is the first message");
msg_send(mq, 2, "Second message with higher priority");
msg_send(mq, 1, "Another message of type 1");
msg_send(mq, 3, "Test message number three");
msg_send(mq, 2, "Final message before queue is full");
msg_queue_print_status(mq);
printf("\n");
// 3. 尝试发送消息到已满队列
printf("--- Attempt to send to full queue ---\n");
int result = msg_send(mq, 4, "This should fail");
if (result == QUEUE_FULL) {
printf("Expected: queue is full, send failed.\n");
}
msg_queue_print_status(mq);
printf("\n");
// 4. 接收几条消息
printf("--- Receiving messages ---\n");
long received_type;
char received_text[MAX_MSG_SIZE];
for (int i = 0; i < 3; i++) {
if (msg_receive(mq, &received_type, received_text, MAX_MSG_SIZE) == 0) {
printf(" Received: type=%ld, text='%s'\n", received_type, received_text);
}
}
msg_queue_print_status(mq);
printf("\n");
// 5. 再发送几条消息,测试环形特性
printf("--- Sending more messages (testing circular behavior) ---\n");
msg_send(mq, 4, "New message after some dequeues");
msg_send(mq, 5, "Another new message");
msg_queue_print_status(mq);
printf("\n");
// 6. 接收剩余的所有消息
printf("--- Receiving all remaining messages ---\n");
while (!msg_queue_is_empty(mq)) {
msg_receive(mq, &received_type, received_text, MAX_MSG_SIZE);
}
msg_queue_print_status(mq);
printf("\n");
// 7. 尝试从空队列接收
printf("--- Attempt to receive from empty queue ---\n");
result = msg_receive(mq, NULL, NULL, 0);
if (result == QUEUE_EMPTY) {
printf("Expected: queue is empty, receive failed.\n");
}
// 8. 清理
msg_queue_destroy(mq);
return 0;
}
看法
-
有一点是
front和rear会一直递增。溢出时间计算
以32位有符号int为例:
最大值:2,147,483,647
假设每秒处理10,000次操作:
达到最大值需要:2,147,483,647 / 10,000 ≈ 214,748 秒 ≈ 2,486 天 ≈ 6.8年
对于大多数应用,在可预见的生命周期内不会溢出。
-
常用的数据结构之一,好用不必多言。
-
AI生成的,理解起来很舒服,有种知识进入大脑的感觉。
本文来自博客园,作者:杨旭0324,转载请注明原文链接:https://www.cnblogs.com/allalonewithyou/p/19332099,个人邮箱:yaonie4444@foxmail.com

浙公网安备 33010602011771号