Function Pointers & Callbacks
Function-কেও variable-এ রাখা যায়
1. Functions Are Values
প্রতিটি function-এর মেমরিতে একটি address থাকে। সেই address একটি variable-এ রাখলে — সেটি function pointer। তার মাধ্যমে function কল করা যায়।
#include <stdio.h>
int add(int a, int b) { return a + b; }
int main(void) {
int (*fp)(int, int) = add;
printf("fp(3, 4) = %d\n", fp(3, 4));
printf("(*fp)(5, 6) = %d\n", (*fp)(5, 6)); // same as fp(5,6)
return 0;
}
2. Reading the Declaration
int (*fp)(int, int);
// ^^^^^ pointer
// to a function taking (int, int) returning int
Complicated syntax সহজ করতে typedef ব্যবহার করুন:
typedef int (*BinaryOp)(int, int);
BinaryOp op = add;
3. Classic Use — qsort
Standard library-র qsort array-র type জানে না — আপনি একটি compare function পাস করেন, সেটাই সব সমস্যা হ্যান্ডল করে।
#include <stdio.h>
#include <stdlib.h>
int cmp_int(const void *a, const void *b) {
int x = *(const int*)a, y = *(const int*)b;
return (x > y) - (x < y); // safe, no overflow
}
int main(void) {
int a[] = {42, 7, 13, 2, 99, 8};
int n = sizeof a / sizeof a[0];
qsort(a, n, sizeof a[0], cmp_int);
for (int i = 0; i < n; i++) printf("%d ", a[i]);
putchar('\n');
return 0;
}
4. Dispatch Tables
একটি operator-char দেখে কোন function কল করবেন — এটি বিশাল switch-এর চেয়ে একটি function-pointer array অনেক পরিষ্কার।
#include <stdio.h>
int op_add(int a, int b) { return a + b; }
int op_sub(int a, int b) { return a - b; }
int op_mul(int a, int b) { return a * b; }
int op_div(int a, int b) { return b ? a / b : 0; }
typedef int (*Op)(int, int);
int main(void) {
Op table[] = { op_add, op_sub, op_mul, op_div };
const char *names = "+-*/";
for (int i = 0; i < 4; i++)
printf("20 %c 6 = %d\n", names[i], table[i](20, 6));
return 0;
}
5. Higher-Order Functions — map
#include <stdio.h>
void map(int *a, int n, int (*fn)(int)) {
for (int i = 0; i < n; i++) a[i] = fn(a[i]);
}
int dbl(int x) { return x * 2; }
int sq(int x) { return x * x; }
int main(void) {
int a[] = {1, 2, 3, 4, 5};
map(a, 5, dbl);
for (int i = 0; i < 5; i++) printf("%d ", a[i]);
putchar('\n');
map(a, 5, sq);
for (int i = 0; i < 5; i++) printf("%d ", a[i]);
putchar('\n');
return 0;
}
6. Practice Problems
- Write a function pointer to
putsand call it.puts-এর function pointer বানিয়ে কল করুন।✨ Show Answer
fp_puts.c#include <stdio.h> int main(void) { int (*fp)(const char *) = puts; fp("Hello via function pointer!"); return 0; } - Sort an array of strings alphabetically with
qsort.qsortদিয়ে string-এর array alphabetically sort করুন।✨ Show Answer
sort_str.c#include <stdio.h> #include <stdlib.h> #include <string.h> int cmp_str(const void *a, const void *b) { return strcmp(*(const char *const*)a, *(const char *const*)b); } int main(void) { const char *arr[] = { "mango", "apple", "banana", "cherry" }; qsort(arr, 4, sizeof arr[0], cmp_str); for (int i = 0; i < 4; i++) puts(arr[i]); return 0; } - Sort an array of Students by GPA (descending) using
qsort.Student array GPA-এর descending ক্রমে sort করুন।✨ Show Answer
sort_students.c#include <stdio.h> #include <stdlib.h> typedef struct { char name[16]; double gpa; } Student; int by_gpa_desc(const void *a, const void *b) { double d = ((const Student*)b)->gpa - ((const Student*)a)->gpa; return (d > 0) - (d < 0); } int main(void) { Student s[] = { {"A",3.55}, {"B",3.92}, {"C",3.72}, {"D",3.61} }; qsort(s, 4, sizeof s[0], by_gpa_desc); for (int i = 0; i < 4; i++) printf("%s %.2f\n", s[i].name, s[i].gpa); return 0; } - Build a calculator that dispatches by operator using a function-pointer table.Operator অনুযায়ী dispatch করা একটি calculator লিখুন।
✨ Show Answer
Section 4-এর
dispatch.c-ই সম্পূর্ণ উত্তর। - Implement
filter: copy only elements wherepredicate(x)is true.filterলিখুন — শুধু যেসব element-এpredicatetrue সেগুলোই কপি করবে।✨ Show Answer
filter.c#include <stdio.h> int filter(const int *in, int n, int *out, int (*pred)(int)) { int k = 0; for (int i = 0; i < n; i++) if (pred(in[i])) out[k++] = in[i]; return k; } int is_even(int x) { return (x & 1) == 0; } int main(void) { int in[] = {1,2,3,4,5,6,7,8,9}, out[9]; int m = filter(in, 9, out, is_even); for (int i = 0; i < m; i++) printf("%d ", out[i]); putchar('\n'); return 0; } - Implement
reduce: fold an array with a binary op.reduceলিখুন — একটি binary op দিয়ে array fold করুন।✨ Show Answer
reduce.c#include <stdio.h> int reduce(const int *a, int n, int init, int (*op)(int, int)) { int acc = init; for (int i = 0; i < n; i++) acc = op(acc, a[i]); return acc; } int add(int a, int b) { return a + b; } int mul(int a, int b) { return a * b; } int main(void) { int a[] = {1,2,3,4,5}; printf("sum = %d\n", reduce(a, 5, 0, add)); printf("prod = %d\n", reduce(a, 5, 1, mul)); return 0; } - Build a simple state machine using function pointers.Function pointer দিয়ে একটি সাধারণ state machine বানান।
✨ Show Answer
fsm.c#include <stdio.h> typedef void (*State)(int *i); void s_idle(int *i); void s_run (int *i); void s_done(int *i); State current = s_idle; void s_idle(int *i) { puts("idle → run"); current = s_run; } void s_run (int *i) { (*i)++; printf("running, step %d\n", *i); if (*i >= 3) current = s_done; } void s_done(int *i) { puts("done"); current = NULL; } int main(void) { int step = 0; while (current) current(&step); return 0; } - Write a generic sort that takes a compare function — implement a minimal insertion sort.একটি compare function নেওয়া generic sort লিখুন।
✨ Show Answer
generic_sort.c#include <stdio.h> #include <string.h> void isort(void *base, int n, int sz, int (*cmp)(const void *, const void *)) { char *a = base, tmp[64]; for (int i = 1; i < n; i++) { memcpy(tmp, a + i * sz, sz); int j = i - 1; while (j >= 0 && cmp(a + j * sz, tmp) > 0) { memcpy(a + (j + 1) * sz, a + j * sz, sz); j--; } memcpy(a + (j + 1) * sz, tmp, sz); } } int cmp_int(const void *a, const void *b) { return *(const int*)a - *(const int*)b; } int main(void) { int a[] = {42, 7, 13, 2, 99}; isort(a, 5, sizeof *a, cmp_int); for (int i = 0; i < 5; i++) printf("%d ", a[i]); putchar('\n'); return 0; } - Declare
int (*fp[5])(int)— explain.int (*fp[5])(int)ব্যাখ্যা করুন।✨ Show Answer
"
fpহলো ৫-টি function-pointer-এর একটি array, যেখানে প্রতিটি function একটিintনেয় এবং একটিintreturn করে।" দরকার হলেtypedef int (*Fn)(int); Fn fp[5];লিখলে পরিষ্কার থাকে। - Declare a pointer to a function that itself returns a function pointer — explain.Function pointer return করা function-এর pointer লিখুন।
✨ Show Answer
// Verbose: int (*(*fp)(int))(int, int); // Clean with typedef: typedef int (*BinOp)(int, int); typedef BinOp (*OpFactory)(int); OpFactory fp;Plain syntax-এ এটি পড়া কষ্টকর — দ্বিতীয় form-ই production code-এ সঠিক।
- Use
typedefto make function-pointer declarations readable.typedefদিয়ে function-pointer declaration পরিষ্কার করুন।✨ Show Answer
Section 2-এর
typedef int (*BinaryOp)(int, int);-ই উদাহরণ। নিয়ম: function-pointer যতই জটিল হোক, first step হলোtypedefকরা। - Write a trivial "plugin" API using function pointers in a struct.Struct-এ function pointer রেখে একটি plugin-এর API লিখুন।
✨ Show Answer
plugin.c#include <stdio.h> typedef struct { const char *name; void (*init)(void); void (*run) (void); void (*stop)(void); } Plugin; void p1_init(void) { puts("p1 init"); } void p1_run (void) { puts("p1 run"); } void p1_stop(void) { puts("p1 stop"); } int main(void) { Plugin p = { "simple", p1_init, p1_run, p1_stop }; p.init(); p.run(); p.stop(); return 0; } - Benchmark idea — switch dispatch vs function-pointer dispatch.Switch বনাম function-pointer dispatch-এর performance তুলনা করুন।
✨ Show Answer
আধুনিক compiler
switch-কে jump-table-এ compile করে, তাই pure performance-এ দুটি প্রায় সমান। Function-pointer dispatch data-driven — runtime-এ table modify করে নতুন আচরণ যোগ করা যায়। Code clarity ও extensibility অনুযায়ী বেছে নিন। - Why does C not allow pointers to methods of structs (like C++)?C কেন C++-এর মতো struct-এর method-এ pointer সমর্থন করে না?
✨ Show Answer
C-তে struct-এর method নেই, শুধু data field আছে। Function আর struct আলাদা — তাই method pointer-এর প্রয়োজনও নেই। আপনি চাইলে struct-এর ভেতরেই একটি function pointer field রেখে manual ভাবে একই pattern পেতে পারেন (Linux kernel-এ
file_operationsএভাবেই কাজ করে)।
Glossary (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
| Function Pointer | A variable that holds the address of a function. | Function-এর address ধারণকারী variable। |
| Callback | A function passed to another function to be called later. | পরে call করার জন্য পাঠানো function। |
| Higher-order Function | A function that takes or returns a function. | Function-কে argument বা return value হিসেবে ব্যবহারকারী function। |
qsort | Generic sort that takes a comparator callback. | Comparator callback নেয় — generic sort। |
| Comparator | A callback returning negative/zero/positive for ordering. | ক্রম নির্ধারণে নেগেটিভ/০/পজিটিভ ফেরতদাতা callback। |
typedef Function Pointer | Alias to keep function pointer syntax readable. | Function pointer-এর syntax পরিষ্কার রাখার alias। |
| Dispatch Table | An array of function pointers indexed by an action. | Action-অনুসারে function-pointer-এর array। |
| Hook | An extension point — a callback the system invokes. | System থেকে call হওয়া callback — extension-point। |
| State Machine | System modeled as states + transitions, often via function pointers. | State + transition-এর মডেল, প্রায়ই function pointer-এ implement। |
| Indirect Call | Calling a function through a pointer instead of by name. | নাম-এ নয়, pointer-এ function call। |
| Plugin | Code loaded at runtime exposing function pointers. | Runtime-এ load হওয়া function-pointer-যুক্ত মডিউল। |
| Closure (manual) | Pair of function pointer + context pointer (no native closures in C). | Function pointer + context pointer — manual closure। |
Summary — Module 22
Function-এর address থাকে — সেটি pointer-এ রেখে কল করা যায়। qsort, event loop, plugin system, state machine — সব function-pointer-এর উপর চলে। typedef দিয়ে declaration পরিষ্কার রাখুন।