Callbacks in C
In C language, a callback is a function that is passed as an argument to another code, which is expected to call back (execute) the argument at a given time. In simple terms, a callback is the process of passing a function (executable code) to another function as an argument, which is then called by the function to which it is passed.
In C, a callback function is passed through a function pointer.
Example:
#include <stdio.h>
void A() {
printf("I am function A");
}
// Callback function
void B(void (*ptr)()) {
// Callback to A
(*ptr)();
}
int main() {
// Function pointer to A()
void (*ptr)() = &A;
// Calling function B and passing
// address of the function A as argument
B(ptr);
return 0;
}
Output
I am function A
Explanation: In this code, a callback function is demonstrated where function B() accepts a function pointer as an argument. Inside B, the passed function pointer ptr is called, which points to function A. This allows function A to be invoked dynamically via B, implementing a callback mechanism.
Syntax of Callback Functions
In C, the syntax for a callback function involves the use of function pointers. A function pointer is a variable that stores the address of a function. The function pointer is then passed to another function, and it can be called using the pointer.
// Function signature of the callback function
void callback_function(void);
// A function that accepts a callback function
void some_function(void (*callback)()) {
// Calling the callback function
callback();
}
Working of Callback in C
The step by step working of callbacks is as follows:
- Define the Callback Function: This is the function that will be called from within another function.
- Declare a Function Pointer: A pointer to the callback function is declared, typically matching the signature of the callback function.
- Pass the Function Pointer: The pointer is passed as an argument to another function.
- Invoke the Callback Function: Inside the receiving function, the callback function is called using the function pointer.
Examples of Callbacks in C
The following examples demonstrate how to use callback functions in C.
Comparing Two Numbers using Callbacks
#include <stdio.h>
// Callback function to compare two numbers
int comp(int a, int b) {
if (a > b) return a;
return b;
}
// Function that accepts a callback for comparison
void Max(int (*callback)(int, int), int x, int y) {
// Calls the callback function
int res = callback(x, y);
printf("Given Numbers: %d, %d\n" ,x, y);
printf("%d is greater", res);
}
int main() {
int x = 7, y = 10;
// Pass the compareNumbers function as callback
Max(comp, x, y);
return 0;
}
Output
Given Numbers: 7, 10 10 is greater
Simple Calculator using Callback
#include <stdio.h>
// Callback functions
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
int mul(int a, int b) {
return a * b;
}
int div(int a, int b) {
return a / b;
}
// General calculator function that accepts a callback
void calc(int a, int b, int (*op)(int, int)) {
// Call the callback function
printf("%d\n", op(a, b));
}
int main() {
int n1 = 10, n2 = 5;
// Using the calculator with addition
printf( "Numbers : %d, %d\n" ,n1, n2);
printf("Sum : ");
calc(n1, n2, add);
// Using the calculator with subtraction
printf("Difference: ");
calc(n1, n2, sub);
return 0;
}
Output
Numbers : 10, 5 Sum : 15 Difference: 5
Applications of Callbacks
The callback concept finds their use in wide variety of cases. Some of them are given below:
- Event-Driven Programming: Callbacks are widely used in GUI applications and other event-driven systems where certain actions (like button clicks) trigger callback functions.
- Sorting Algorithms: Callbacks can be used to define comparison functions in sorting functions like qsort() in the C Standard Library.
- Asynchronous Operations: Callbacks are used to handle asynchronous tasks, where a function continues its execution and calls the callback when the task completes.
- Custom Behaviours: Callbacks allow the programmer to pass custom behaviour to functions. For example, callbacks can define how certain operations are performed without modifying the core logic of the function.