The stdarg Macros
va_list, va_start, va_arg.
The stdarg Macros is a free C Academy lesson on CoddyKit. This is 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, and your progress syncs across the web and the CoddyKit app. The C Academy course includes 4 lessons in total.
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.
Learn C with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 39
- Lessons
- 144
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. 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. The C Academy course includes 4 lessons in total.
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, so you can start here or from the beginning and move at your own pace. This is lesson 1 of 4.
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