在软件开发中,发布订阅模式(Publish-Subscribe Pattern)是一种非常重要的事件驱动编程设计思想。它允许组件之间松耦合地通信:发布者(Publisher)发送消息,而无需知道谁会接收;订阅者(Subscriber)监听感兴趣的消息,而无需知道谁发布了它。这种模式在 GUI 编程、消息中间件、嵌入式系统等领域广泛应用。
虽然 C 语言不像 Java 或 Python 那样内置面向对象特性,但我们依然可以用结构体和函数指针来优雅地实现 C语言发布订阅模式。本文将从零开始,带你一步步构建一个简易但完整的发布订阅系统,适合编程小白理解。

我们首先定义几个关键结构:
#include <stdio.h>#include <stdlib.h>#include <string.h>// 订阅者回调函数类型typedef void (*subscriber_callback_t)(const char* topic, const void* data);// 单个订阅者节点typedef struct SubscriberNode { subscriber_callback_t callback; struct SubscriberNode* next;} SubscriberNode;// 主题条目(哈希表中的一个桶)typedef struct TopicEntry { char* topic_name; SubscriberNode* subscribers; struct TopicEntry* next; // 用于处理哈希冲突} TopicEntry;// 事件总线typedef struct EventBus { TopicEntry** buckets; // 哈希表数组 int bucket_count;} EventBus;
接下来我们实现初始化、订阅、发布等关键功能。
#define DEFAULT_BUCKET_COUNT 16unsigned int hash(const char* str) { unsigned int hash = 5381; int c; while ((c = *str++)) hash = ((hash << 5) + hash) + c; // djb2 算法 return hash;}EventBus* event_bus_create() { EventBus* bus = (EventBus*)malloc(sizeof(EventBus)); bus->bucket_count = DEFAULT_BUCKET_COUNT; bus->buckets = (TopicEntry**)calloc(DEFAULT_BUCKET_COUNT, sizeof(TopicEntry*)); return bus;}
void event_bus_subscribe(EventBus* bus, const char* topic, subscriber_callback_t callback) { unsigned int index = hash(topic) % bus->bucket_count; TopicEntry* entry = bus->buckets[index]; // 查找是否已存在该主题 while (entry) { if (strcmp(entry->topic_name, topic) == 0) { // 添加新订阅者到链表末尾 SubscriberNode* new_node = (SubscriberNode*)malloc(sizeof(SubscriberNode)); new_node->callback = callback; new_node->next = NULL; if (entry->subscribers == NULL) { entry->subscribers = new_node; } else { SubscriberNode* tail = entry->subscribers; while (tail->next) tail = tail->next; tail->next = new_node; } return; } entry = entry->next; } // 主题不存在,创建新条目 TopicEntry* new_entry = (TopicEntry*)malloc(sizeof(TopicEntry)); new_entry->topic_name = strdup(topic); new_entry->subscribers = NULL; new_entry->next = bus->buckets[index]; bus->buckets[index] = new_entry; // 添加第一个订阅者 SubscriberNode* new_node = (SubscriberNode*)malloc(sizeof(SubscriberNode)); new_node->callback = callback; new_node->next = NULL; new_entry->subscribers = new_node;}
void event_bus_publish(EventBus* bus, const char* topic, const void* data) { unsigned int index = hash(topic) % bus->bucket_count; TopicEntry* entry = bus->buckets[index]; while (entry) { if (strcmp(entry->topic_name, topic) == 0) { SubscriberNode* sub = entry->subscribers; while (sub) { sub->callback(topic, data); sub = sub->next; } break; } entry = entry->next; }}
下面是一个完整的测试程序,演示如何使用我们构建的 消息传递机制C语言 实现:
void on_temperature_update(const char* topic, const void* data) { float temp = *(const float*)data; printf("[温度传感器] 收到更新: %.2f°C\n", temp);}void on_log_message(const char* topic, const void* data) { printf("[日志模块] 收到消息: %s\n", (const char*)data);}int main() { EventBus* bus = event_bus_create(); // 订阅主题 event_bus_subscribe(bus, "sensor/temperature", on_temperature_update); event_bus_subscribe(bus, "system/log", on_log_message); // 发布消息 float temp = 25.6f; event_bus_publish(bus, "sensor/temperature", &temp); const char* msg = "系统启动成功!"; event_bus_publish(bus, "system/log", msg); // 注意:实际项目中应添加内存释放函数 return 0;}
通过以上代码,我们成功在 C 语言中实现了基本的 观察者模式C实现。这个系统具有以下优点:
对于嵌入式或资源受限环境,你可以简化哈希表,改用线性查找;也可以加入线程安全机制(如互斥锁)以支持多线程场景。
掌握 C语言发布订阅模式 不仅能提升你的架构设计能力,还能为学习更复杂的 事件驱动编程C语言 框架打下坚实基础。快动手试试吧!
本文由主机测评网于2025-12-03发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025122533.html