They are one of those most useful things in C! They allow you to make a lot more modular software.
Callbacks
eg,
typedef void (*serial_data_callback)(int length, unsigned char* data);
void serial_port_data_received(serial_data_callback callback)
{
on_data_received = callback;
}
void data_received(int length, unsigned char* data)
{
if(on_data_received != NULL) on_data_received(length, data);
}
this means in your code you can use the general serial routines.....then you might have two things that use serial, modbus and terminal
serial_port_data_received(modbus_handle_data);
serial_port_data_received(terminal_handle_data);
and they can implement the callback function and do what's appropriate.
They allow for Object Oriented C code. It's a simple way to create "Interfaces" and then each concrete type might implement things different. For this, generally you will have a struct that will have function pointers, then functions to implement each function pointer, and a creation function that will setup the function pointers with the right functions.
typedef struct
{
void (*send)(int length, unsigned char* data);
} connection_t;
void connection_send(connection_t* self, int length, unsigned char* data)
{
if(self->send != NULL) self->send(length, data);
}
void serial_send(int length, unsigned char* data)
{
// send
}
void tcp_send(int length, unsgined char* data)
{
// send
}
void create_serial_connection(connection_t* connection)
{
connection->send = serial_send;
}
then other code can use use a connection_t without caring whether its via serial, tcp, or anything else that you can come up with.