pointers-memory · intermediate · ~15 min
Pair function pointers with arbitrary user-data context pointers to build decoupled event-driven systems.
Asynchronous frameworks (like GUI toolkits, libuv, and Linux kernel drivers) use callback function pointers paired with a void *user_data context pointer to maintain state without global variables.
Implement:
typedef void (*event_cb_t)(int event_type, void *user_data);
struct event_listener {
int event_type;
event_cb_t cb;
void *user_data;
};
struct event_bus {
struct event_listener listeners[16];
size_t count;
};
void event_bus_init(struct event_bus *bus);
int event_bus_subscribe(struct event_bus *bus, int event_type, event_cb_t cb, void *user_data);
int event_bus_publish(const struct event_bus *bus, int event_type);
event_bus_init: sets bus->count = 0.event_bus_subscribe:bus == NULL, cb == NULL, or bus->count >= 16, return -1.bus->count and increment bus->count. Return 0.event_bus_publish:bus == NULL, return 0.event_type, invoke l->cb(event_type, l->user_data).bus: event bus pointer; event_type: integer event id; cb: callback function; user_data: context pointer.
subscribe returns 0 or -1. publish returns count of notified listeners.
C11 freestanding. Up to 16 subscribers.
#include <stddef.h>
/* The harness provides:
typedef void (*event_cb_t)(int event_type, void *user_data);
struct event_listener {
int event_type;
event_cb_t cb;
void *user_data;
};
struct event_bus {
struct event_listener listeners[16];
size_t count;
};
*/
void event_bus_init(struct event_bus *bus) {
(void)bus;
}
int event_bus_subscribe(struct event_bus *bus, int event_type, event_cb_t cb, void *user_data) {
(void)bus; (void)event_type; (void)cb; (void)user_data;
return -1;
}
int event_bus_publish(const struct event_bus *bus, int event_type) {
(void)bus; (void)event_type;
return 0;
}
Forgetting to pass user_data to the callback; not checking bus->count < 16.
No listeners for event returns 0; multiple listeners for same event all receive invocation; full bus returns -1 on subscribe.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.