The stdarg Macros
va_list, va_start, va_arg.
The stdarg Macros is a free C Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What are variadic functions?
A variadic function accepts a variable number of arguments. You have used one already: printf can take any number of values.
C lets you write your own using the <stdarg.h> macros.
#include <stdio.h>
int main(void) {
printf("%d %d %d\n", 1, 2, 3);
printf("%s\n", "any count of args");
return 0;
}The ellipsis
You declare a variadic function with ... (the ellipsis) as the last parameter.
At least one named parameter must come before it, so the function knows where the variable part begins.
#include <stdio.h>
#include <stdarg.h>
void demo(int count, ...) {
printf("This function takes %d extra args\n", count);
}
int main(void) {
demo(3, 10, 20, 30);
return 0;
}Including stdarg.h
To read the variable arguments you need #include <stdarg.h>.
It defines the type va_list and the macros va_start, va_arg, and va_end.
#include <stdio.h>
#include <stdarg.h>
void show(int n, ...) {
va_list args;
va_start(args, n);
va_end(args);
printf("set up and cleaned up\n");
}
int main(void) {
show(2, 5, 6);
return 0;
}va_list and va_start
Declare a va_list variable to track the current position. Then call va_start(list, last), passing the last named parameter.
This points the list at the first variable argument.
#include <stdio.h>
#include <stdarg.h>
void first(int count, ...) {
va_list args;
va_start(args, count);
int value = va_arg(args, int);
printf("first variadic arg = %d\n", value);
va_end(args);
}
int main(void) {
first(1, 99);
return 0;
}va_arg: reading values
va_arg(list, type) returns the next argument and advances the list. You must tell it the exact type to read.
Each call moves forward by one argument.
#include <stdio.h>
#include <stdarg.h>
void three(int n, ...) {
va_list args;
va_start(args, n);
int a = va_arg(args, int);
int b = va_arg(args, int);
int c = va_arg(args, int);
printf("%d %d %d\n", a, b, c);
va_end(args);
}
int main(void) {
three(3, 7, 8, 9);
return 0;
}va_end: cleanup
Always call va_end(list) when you finish reading. It performs any cleanup the platform needs.
Forgetting it leads to undefined behavior on some systems.
#include <stdio.h>
#include <stdarg.h>
int add_two(int dummy, ...) {
va_list args;
va_start(args, dummy);
int sum = va_arg(args, int) + va_arg(args, int);
va_end(args);
return sum;
}
int main(void) {
printf("%d\n", add_two(0, 4, 6));
return 0;
}Knowing how many arguments
The macros cannot tell you how many arguments were passed. You must convey that yourself.
A common approach is a leading count parameter, as in sum(3, a, b, c).
#include <stdio.h>
#include <stdarg.h>
int sum(int count, ...) {
va_list args;
va_start(args, count);
int total = 0;
for (int i = 0; i < count; i++)
total += va_arg(args, int);
va_end(args);
return total;
}
int main(void) {
printf("%d\n", sum(4, 1, 2, 3, 4));
return 0;
}Using a sentinel value
Another way to mark the end is a sentinel: a special terminating value the caller must include, such as -1 or NULL.
Loop until you read the sentinel.
#include <stdio.h>
#include <stdarg.h>
int sum_until_neg(int first, ...) {
va_list args;
va_start(args, first);
int total = first, v;
while ((v = va_arg(args, int)) != -1)
total += v;
va_end(args);
return total;
}
int main(void) {
printf("%d\n", sum_until_neg(10, 20, 30, -1));
return 0;
}Default argument promotions
Variadic arguments undergo default promotions: char and short become int, and float becomes double.
So always read small integers as int and floats as double with va_arg.
#include <stdio.h>
#include <stdarg.h>
void show_double(int n, ...) {
va_list args;
va_start(args, n);
double d = va_arg(args, double);
printf("%.2f\n", d);
va_end(args);
}
int main(void) {
show_double(1, 3.5f);
return 0;
}Copying a va_list
If you need to traverse the arguments twice, use va_copy(dest, src) to duplicate the list before reading.
You cannot reuse a va_list after va_end without restarting via va_start.
#include <stdio.h>
#include <stdarg.h>
void twice(int n, ...) {
va_list a, b;
va_start(a, n);
va_copy(b, a);
printf("%d %d\n", va_arg(a, int), va_arg(b, int));
va_end(a);
va_end(b);
}
int main(void) {
twice(1, 42);
return 0;
}Computing an average
Combining the count pattern with float reading, we can average a list of numbers passed variadically.
#include <stdio.h>
#include <stdarg.h>
double average(int count, ...) {
va_list args;
va_start(args, count);
double sum = 0;
for (int i = 0; i < count; i++)
sum += va_arg(args, double);
va_end(args);
return sum / count;
}
int main(void) {
printf("%.2f\n", average(3, 2.0, 4.0, 6.0));
return 0;
}Quick Check
Test your understanding of the stdarg macros.
Recap
You learned the variadic mechanism:
- Declare with
...after at least one named parameter. va_start(list, last)begins,va_arg(list, type)reads,va_end(list)cleans up.- The macros do not know the count — use a count parameter or a sentinel.
- Mind default promotions: read small ints as
int, floats asdouble.
Frequently asked questions
Is the “The stdarg Macros” lesson free?
Yes — the full text of “The stdarg Macros” is free to read here on the web, and the C Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C Academy course, upgrade to CoddyKit PRO.
What will I learn in “The stdarg Macros”?
va_list, va_start, va_arg. You practise C Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C Academy?
No prior experience is required. C Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “The stdarg Macros” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C Academy lesson?
Yes. Every C Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The stdarg Macros
- Writing printf-like Functions
- Type Safety Concerns
- Practical Examples