5.1.13 · Coding › C Programming
Ek normal pointer data ka address store karta hai. Ek function pointer code ka address store karta hai — wo jagah memory mein jahan ek function ki instructions shuru hoti hain. Kyunki ek function memory mein bilkul ek variable ki tarah kahin na kahin rehta hai, tum uska address le sakte ho, use ek variable mein save kar sakte ho, aur baad mein us variable ke through "call" kar sakte ho. Yahi cheez tumhe allow karti hai ki runtime par decide karo kaun sa function chalana hai, instead of use hardcode karne ke.
Intuition The 80/20 core idea
Normally sort(arr) sirf ek fixed tarike se sort karna jaanta hai. Par agar tum sort ko batana chaho "inhe IS tarah compare karo"? Tum use ek function pass karte ho jo comparing karta hai. Library tumhara function call karti hai jab bhi use compare karna hota hai — yahi ek callback hai. Function pointers "behaviour" ko "data jo tum pass kar sako" mein badal dete hain. Yahi ek idea qsort, event handlers, plugin systems, aur dispatch tables ko power karta hai.
Ek function pointer ek aisi variable hai jiska value kisi function ka address hota hai. Uska type function ki return type aur parameter types encode karta hai, kyunki compiler ko jaanna chahiye ki call kaise setup karni hai (kitne args, kya sizes, kya wapas milega).
Ek function ka naam uske address mein decay ho jaata hai. Toh int add(int,int) ke liye:
add → woh function
&add → uska address (same value, type int(*)(int,int))
add → zyaadatar expressions mein woh address mein bhi decay ho jaata hai
Ek normal declaration se shuru karo aur use step by step transform karo.
Worked example Building the declaration
Ek function: int add(int a, int b); — naam hai add.
Naam ko (*p) se replace karo: int (*p)(int, int);
*p ke around parentheses kyun? Unke bina, int *p(int,int) ka matlab hai "ek function jo int* return karta hai". () pehle * ko p se bind karte hain, p ko pointer banate hain, phir (int,int) usp apply hota hai. Parentheses change karte hain ki * kiska hai.
Inside-out padho: p ek pointer hai (*p) ek aise function ki taraf (int,int) jo int return karta hai.
int add ( int a , int b ) { return a + b; }
int ( * p)( int , int ); // declare
p = add; // assign (add decays to &add); p = &add; bhi kaam karta hai
int r1 = p ( 3 , 4 ); // call via pointer -> 7
int r2 = ( * p)( 3 , 4 ); // explicit deref, bhi 7 (identical)
p(3,4) aur (*p)(3,4) dono kyun kaam karte hain?
Calling ke liye ek function chahiye, aur ek function pointer ko dereference karna ek function deta hai jo turant wapas pointer mein decay ho jaata hai . Toh language dono forms ko identically treat karti hai — C yahan purpose se lenient hai.
Ek callback = tum ek function pointer doosre function ko dete ho, aur woh tumhe wapas call karta hai.
// qsort signature (from <stdlib.h>):
void qsort ( void * base , size_t n , size_t size ,
int ( * cmp)( const void * , const void * ));
Worked example Sorting ints ascending with qsort
int cmp_asc ( const void * a , const void * b ) {
int x = * ( const int * )a; // Cast kyun? qsort void* pass karta hai; hum jaante hain ye ints hain
int y = * ( const int * )b;
return (x > y) - (x < y); // Yeh kyun? overflow risk ke bina -1/0/+1 return karta hai x-y ke
}
int arr [] = { 3 , 1 , 2 };
qsort (arr, 3 , sizeof ( int ), cmp_asc); // arr -> {1,2,3}
Yeh step kyun (trick (x>y)-(x<y))? qsort ko sirf sign chahiye: negative agar a<b, 0 agar equal, positive agar a>b. Large/negative ints ke liye x - y overflow ho sakta hai; comparison form hamesha safe hai.
Worked example Descending — just swap
int cmp_desc ( const void * a , const void * b ) {
int x = * ( const int* )a, y = * ( const int* )b;
return (y > x) - (y < x); // Kyun? order reverse karne ke liye x,y ke roles flip karo
}
Same qsort call, alag behaviour — sirf pass ki gayi function badli. Yahi pura point hai.
switch with a table
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 ( * ops [ 3 ])( int , int ) = { add, sub, mul }; // 3 fn pointers ka array
int r = ops [ 1 ]( 10 , 4 ); // -> 6, sub ko call karta hai
Yeh powerful kyun hai: if/else chains ki jagah, tum behaviour mein index karte ho. ops[opcode](x,y) — clean, extensible, O(1) dispatch. Yahi tarah interpreters aur virtual machines kaam karte hain.
typedef int ( * BinOp)( int , int ); // BinOp = "int(int,int) ka pointer"
BinOp p = add; // Kyun? ab ek normal variable jaisa padhta hai
void run (BinOp f ) { f ( 1 , 2 ); } // Kyun? clean parameter type
typedef kyun? Raw syntax int (*ops[3])(int,int) padhna mushkil hai aur galat karna aasaan. typedef type ko ek baar naam deta hai; uske baad sab kuch ordinary code jaisa padhta hai.
Common mistake Forgetting the parentheses
int *p(int,int); likhna sahi lagta hai kyunki "* ek pointer banata hai."
Kyun sahi lagta hai: data declarations mein int *p hai ek pointer.
Sachai: yahan () zyaada tight bind karte hain, toh yeh ek function declare karta hai jo int* return karta hai , function ka pointer nahi.
Fix: naam ko hamesha wrap karo: int (*p)(int,int).
Common mistake Signature mismatch
Ek double f(double) ko int(*)(int) pointer mein assign karna aur use call karna.
Kyun sahi lagta hai: "yeh sirf ek address hai, addresses sab same size ke hote hain."
Sachai: type CPU ko batata hai ki args kaise pass karein aur return value kaise padhen. Galat type → garbage / crash (undefined behaviour). Fix: return aur har parameter bilkul match karo.
cmp returning a - b in qsort
Kyun sahi lagta hai: subtraction aam taur par sahi sign deta hai.
Sachai: extreme values ke liye integer overflow sign ko flip kar sakta hai, sort ko tod ke.
Fix: return (a>b) - (a<b);
Common mistake Calling through a NULL or uninitialized function pointer
Ek uninitialized int (*p)(int,int); garbage hold karta hai; p(1,2) call karna random memory mein jump karta hai → crash.
Fix: hamesha initialize karo (= NULL) aur call karne se pehle check karo.
Recall Answer padhne se pehle outputs predict karo
int (*ops[2])(int,int) = {add, sub}; diya hai add/sub upar ki tarah:
ops[0](5,2) → ?
ops[1](5,2) → ?
(*ops[1])(5,2) → ?
Answers: 1) 7 2) 3 3) 3 (explicit deref ≡ plain call).
Recall Feynman: 12-saal ke bacche ko samjhao
Ek TV remote imagine karo. Remote mein buttons hain, aur har button kuch karne ke liye wired hai (volume badhao, channel badlo). Ek function pointer ek aisa button hai jiska wiring tum rewire kar sakte ho . Tum keh sakte ho "jab main YEH button dabaaun, WOH action chalao." Ek callback tab hota hai jab tum TV ko ek button dete ho aur kehte ho "jab kuch ho to ise dabao." Toh tum kisi ko ek button (ek function) dete ho, aur woh tumhare liye sahi waqt par use dabata hai. Tum action decide karte ho; woh timing decide karte hain.
"Star hugs the name, parens make the game."
(*name) — star ko naam ko parentheses mein hug karna chahiye, warna tumne ek function declare kar diya, function ka pointer nahi.
Ek function pointer kya store karta hai? Ek function ka address (memory mein uske code ki shuruat).
Ek pointer p declare karo jo do ints lene wale aur int return karne wale function ki taraf point kare. int (*p)(int, int);
int (*p)(int,int) mein parentheses kyun zaroori hain?Unke bina int *p(int,int) ek int* return karne wala function declare karta hai; parens * ko pehle p se bind karte hain.
Function pointer p ko args 3,4 ke saath call karne ke do equivalent tarike? p(3,4) aur (*p)(3,4).
Callback kya hota hai? Ek function pointer jo tum doosre function ko pass karte ho taaki woh sahi waqt par tumhara code call kar sake.
qsort mein comparator parameter ka type kya hai?int (*)(const void *, const void *).
Comparator mein x-y ki jagah (x>y)-(x<y) kyun use karte hain? Yeh integer overflow ke risk ke bina sahi sign return karta hai.
3 function pointers int(int,int) ka array kaise likhte hain? int (*ops[3])(int, int);
pointer to int(int,int) ko BinOp naam dene wala typedef do.typedef int (*BinOp)(int, int);
Uninitialized function pointer ka khatre kya hai? Use call karna garbage memory mein jump karta hai → undefined behaviour / crash; NULL se initialize karo aur check karo.
Kya add (ek function name) &add ke barabar hai? Haan — ek function name uske address mein decay ho jaata hai; dono ka type int(*)(int,int) hai.
Pointers in C — data pointers vs code pointers
qsort aur C Standard Library — real-world callback
Arrays in C — function pointers ke arrays as dispatch tables
typedef — complex declarations ko tame karna
void pointers — callbacks mein generic args
Polymorphism — OOP languages is idea ko kaise implement karti hain (vtables = function pointers ke arrays)
Return type plus param types
Declaration ret *name params
Parentheses bind * to name
Choose function at runtime