Function Pointers & Callbacks

Function-কেও variable-এ রাখা যায়

~30 min Advanced 14 practice problems Live code

1. Functions Are Values

প্রতিটি function-এর মেমরিতে একটি address থাকে। সেই address একটি variable-এ রাখলে — সেটি function pointer। তার মাধ্যমে function কল করা যায়।

fp_basics.c
#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 পাস করেন, সেটাই সব সমস্যা হ্যান্ডল করে।

qsort_int.c
#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 অনেক পরিষ্কার।

dispatch.c
#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

map.c
#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

  1. Write a function pointer to puts and 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;
    }
  2. 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;
    }
  3. 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;
    }
  4. Build a calculator that dispatches by operator using a function-pointer table.
    Operator অনুযায়ী dispatch করা একটি calculator লিখুন।
    ✨ Show Answer

    Section 4-এর dispatch.c-ই সম্পূর্ণ উত্তর।

  5. Implement filter: copy only elements where predicate(x) is true.
    filter লিখুন — শুধু যেসব element-এ predicate true সেগুলোই কপি করবে।
    ✨ 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;
    }
  6. 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;
    }
  7. 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;
    }
  8. 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;
    }
  9. Declare int (*fp[5])(int) — explain.
    int (*fp[5])(int) ব্যাখ্যা করুন।
    ✨ Show Answer

    "fp হলো ৫-টি function-pointer-এর একটি array, যেখানে প্রতিটি function একটি int নেয় এবং একটি int return করে।" দরকার হলে typedef int (*Fn)(int); Fn fp[5]; লিখলে পরিষ্কার থাকে।

  10. 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-এ সঠিক।

  11. Use typedef to make function-pointer declarations readable.
    typedef দিয়ে function-pointer declaration পরিষ্কার করুন।
    ✨ Show Answer

    Section 2-এর typedef int (*BinaryOp)(int, int);-ই উদাহরণ। নিয়ম: function-pointer যতই জটিল হোক, first step হলো typedef করা।

  12. 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;
    }
  13. 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 অনুযায়ী বেছে নিন।

  14. 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 (শব্দকোষ)

TermMeaningবাংলায়
Function PointerA variable that holds the address of a function.Function-এর address ধারণকারী variable।
CallbackA function passed to another function to be called later.পরে call করার জন্য পাঠানো function।
Higher-order FunctionA function that takes or returns a function.Function-কে argument বা return value হিসেবে ব্যবহারকারী function।
qsortGeneric sort that takes a comparator callback.Comparator callback নেয় — generic sort।
ComparatorA callback returning negative/zero/positive for ordering.ক্রম নির্ধারণে নেগেটিভ/০/পজিটিভ ফেরতদাতা callback।
typedef Function PointerAlias to keep function pointer syntax readable.Function pointer-এর syntax পরিষ্কার রাখার alias।
Dispatch TableAn array of function pointers indexed by an action.Action-অনুসারে function-pointer-এর array।
HookAn extension point — a callback the system invokes.System থেকে call হওয়া callback — extension-point।
State MachineSystem modeled as states + transitions, often via function pointers.State + transition-এর মডেল, প্রায়ই function pointer-এ implement।
Indirect CallCalling a function through a pointer instead of by name.নাম-এ নয়, pointer-এ function call।
PluginCode 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 পরিষ্কার রাখুন।

Next Module → Modular Programming — header, Makefile, library।