Variadic functions
This is the new concept that we learn during this project. It is essential to understand it well before moving on.
The functions you have used and created so far in your course had fixed arguments. There could be several, but you always knew in advance what arguments you would need.
For example strlen only takes a string as input (int ft_strlen(char *str))
and split takes two elements as input (**ft_split(char const *s, char c))
. You get the idea.
A variadic function is a function which accepts a variable number of arguments. It is characterized by the "..." in a function.
The variadic function must have at least one mandatory argument. There is no minimum for the number of variable arguments.
When someone calls the printf function, we don't know in advance how many elements the person wants to display. In other words, we don't know how many times the format specifier will be used.
In the above case, the function takes two other arguments, in addition to the initial string. If you knew in advance how many arguments you were using and of what type, the function could be rewritten in this way:
Thankfully the C language is well done. There is no need to rewrite the printf function every time you change the number of arguments in input. You will just have to include the "stdarg" library which will allow you to use a new type of variable, va_list
, and 3 very useful macros: va_start
, va_arg
& va_end
Let's take a closer look at how to use them
va_list, va_start, va_end & va_arg
va_list
- new object type
va_list
- new object typeva_list
is an object type suitable for holding the information needed by the macros va_start
, va_copy,
va_arg
, and va_end
(that you will understand in a few minutes). In other words, it is a list that will contain all the dynamic arguments.
To create a variable of this type, you will have to do it the same way as any other variable.
This will create the list of dynamic arguments which can be illustrated as follows
In this example, the printf function takes 2 extra arguments, in addition to the mandatory argument. These two arguments are the variable arguments and will be stored in the previously created variable of type valist, thanks to va_start
.
va_start
- function macro
va_start
- function macroThe macro va_start
function will somehow initialize everything, before we start moving through our variable argument list (va_list). You have to write it like that:
var
is a variable of type arg_list (args for us)parameterN
is the named parameter preceding the first dynamic parameter (in our case, with printf, it would be the initial string) - in other words, it's the mandatory argument
Its purpose is to set the stage and define which elements will be stable and which will vary. This is when your va_list variable will have all the elements in the table.
va_start
must be called before any use of va_arg - otherwise your va_list variable/table will be empty.
va_arg
- function macro
va_arg
- function macroNow that everything is ready, you can start using and playing with your variable arguments. This can be done with va_arg.
This macro allows access to the arguments of the variadic function. Each time va_arg
is called, you move to the next argument.
va_arg
will take as argument first the list of dynamic arguments we had defined at the very beginning (va_list object) and the type of the variable of the next argument.
Let's go back to our example
The length of our variable argument list (args) is 2. There is a string argument in first position and an int argument in second position.
If you want to access the first argument, you will have to call va_arg
once and specify the type of the argument. In this case, the first argument is a string, that will be defined by a pointer.
If you want to access the second argument, you do the same thing. But this time the type of the argument is an "int".
Obviously, this is just a theoretical example so that you can understand how va_arg works. In practice, since we don't know in advance how many arguments the function will take, you can imagine that you will have to create conditions for each specified format.
va_end
- function macro
va_end
- function macroOnce you have finished your program, don't forget to clean up the object you initialized by calling va_start.
va_end
can modify the object, which was called "args" in our previous example, so that it is no longer usable.
va_end()
will free the allocated memory.
Now that you have the basics and have understood the most complicated part (aka the variadic functions (scary huh ?)) you can try to create your own printf : the legendary ft_printf. Let's do it together step by step.
Last updated
Was this helpful?