Variadic functions — va_list, va_start, va_arg, va_end
5.1.29· Coding › C Programming
WHY — iska zaroorat hi kyun hai?
Is power ki cost: compiler aapko check karna band kar deta hai. Sirf aap decide karte ho ki kitne args hain aur har ek ka type kya hai. Galat promise kiya → undefined behavior.
WHAT — chaar pieces kya hain?
HOW — pehle principles se kaise kaam karta hai
Jab aap f(a, b, c, d) call karte ho, toh arguments kahin aisa rakhe jaate hain jahan callee reach kar sake (bahut se ABIs mein: stack aur/ya registers mein, ek known order mein). Named parameters pehle slots consume karte hain. Baaki bytes wahan hain lekin unnamed.

Worked Example 1 — n integers ka sum (count method)
#include <stdarg.h>
#include <stdio.h>
int sum(int n, ...) { // n tells us HOW MANY follow
va_list ap;
va_start(ap, n); // cursor starts after 'n'
long total = 0;
for (int i = 0; i < n; i++)
total += va_arg(ap, int); // pull each as int
va_end(ap);
return (int)total;
}
int main(void){ printf("%d\n", sum(3, 10, 20, 30)); } // 60| Step | Code | Yeh step kyun? |
|---|---|---|
| 1 | int sum(int n, ...) |
Ek named param n chahiye taaki va_start ko anchor mile aur hum count jaanein. |
| 2 | va_start(ap, n) |
Cursor ko n ke theek baad — pehle ... argument par — point karo. |
| 3 | va_arg(ap, int) in loop |
Exactly n times padho aur aage badho; type int usi se match karta hai jo humne pass kiya. |
| 4 | va_end(ap) |
Return karne se pehle required cleanup. |
Worked Example 2 — sentinel-terminated string concatenator
#include <stdarg.h>
#include <string.h>
size_t total_len(const char *first, ...) {
va_list ap;
va_start(ap, first);
size_t len = strlen(first);
const char *s;
while ((s = va_arg(ap, const char*)) != NULL) // stop at NULL
len += strlen(s);
va_end(ap);
return len;
}
// total_len("ab", "cde", "f", NULL) == 6| Step | Yeh step kyun? |
|---|---|
first is named |
Anchor milta hai; aur yahan yeh natural bhi hai (list mein hamesha ek pehla item hota hai). |
loop until NULL |
Koi count pass nahi kiya gaya, toh ek sentinel end mark karta hai. Caller ko NULL zaroor pass karna hoga. |
va_arg(ap, const char*) |
Humne pointers promise kiye — type args se match karni chahiye. |
Worked Example 3 — va_copy se re-scanning
double average(int n, ...) {
va_list ap, ap2;
va_start(ap, n);
va_copy(ap2, ap); // duplicate cursor BEFORE consuming
long sum = 0;
for (int i = 0; i < n; i++) sum += va_arg(ap, int);
va_end(ap);
// ... could re-walk ap2 for a second pass ...
va_end(ap2);
return n ? (double)sum / n : 0.0;
}Common Mistakes (Har ek ko Steel-man karo)
Recall Feynman: 12-saal ke bachche ko samjhao
Socho ek conveyor belt hai jisme boxes aa rahe hain, aur tum shuru mein khade ho. Tumhe nahi pata kitne boxes aa rahe hain. va_start kehta hai "pehle box par jao." va_arg(int) kehta hai "agla box kholo, expect karo ki ek number hai, use lo, aur agle box par chale jao." Lekin yahan trick hai: belt tumhe nahi batati ki kab khatam hoti hai aur boxes par label nahi hota ki andar kya hai. Isliye pehle se agree karna hota hai — ya toh koi batata hai "3 boxes hain," ya aakhri box ek special khaali "STOP" box hota hai. Agar count ya contents galat guess karo, toh haath mein kuch nahi aata. va_end hai jab kaam ho jaata hai toh haath neeche karna.
Active Recall
Variadic macros kaunsa header declare karta hai?
<stdarg.h>va_list kya hai?
va_start(ap, last) kya karta hai?
ap ko aakhri named parameter last ke theek baad point karne ke liye initialize karta hai.va_arg(ap, type) kya karta hai?
type ke roop mein interpret karke return karta hai, aur cursor ko aage badhata hai.va_end kyun call karna zaroori hai?
va_list ka required cleanup karta hai function return karne se pehle.Ek variadic function mein ≥1 named parameter kyun hona chahiye?
va_start ko apne anchor point ke roop mein aakhri named parameter ka naam chahiye hota hai.Kitne variadic args hain yeh jaanne ke do tarike?
NULL/-1).float arguments mein kaunsa promotion hota hai?
double mein promote kiya jaata hai, isliye va_arg(ap, double) use karo.char/short arguments mein kaunsa promotion hota hai?
int mein promote kiya jaata hai, isliye va_arg(ap, int) use karo.va_copy(dst, src) kis kaam aata hai?
va_list ko portably duplicate karne ke liye taaki arguments ek se zyada baar scan kiye ja sakein.va_arg type mismatch se UB kyun hota hai?
Kya va_list ko rewind kar sakte hain?
va_copy se copy karo.Connections
- C Standard Library —
printf/scanf/vfprintfvariadic hain. - Default Argument Promotions — kyun
char→int,float→double. - Calling Conventions and the Stack —
va_argke liye args kaise lay out hote hain. - Function Pointers in C — variadic functions ko pass karna.
- Undefined Behavior in C — yahan dominant risk class yahi hai.
- Format String Vulnerabilities — unchecked variadic args ki security cost.