Variadic Functions Explained

The Ultimate Guide to Variable Arguments in C

Samuel Selasi
7 min readJan 28, 2023
PC: Here

In this blog post, we will delve into the intricacies of variadic functions in C programming language. We will examine the functionality of built-in variadic functions such as printf and scanf, and explore how to effectively utilize them in our code. Additionally, we will delve into the process of creating custom variadic functions using the va_list, va_start, va_arg, and va_end macros, and learn how to manage a variable number of arguments passed to the function.

Furthermore, this post will examine real-world use cases for variadic functions, such as determining the sum of an undetermined number of integers or displaying a variable number of strings to the console. Through the use of examples and clear explanations, we aim to impart a comprehensive understanding of variadic functions and their potential for enhancing the functionality of our code.

As we embark on this technical exploration of variadic functions in C programming language, we recommend taking a few moments to relax and enjoy the memes included in the post. Let us begin!

Definition

A variadic function is a function in C programming language that can take a variable number of arguments. These functions are particularly useful in situations where the number of arguments needed is not known beforehand.

Variadic functions are supported in C through the use of a special set of macros defined in the <stdarg.h> header file. These macros include va_list, va_start, va_arg and va_end, and they allow the programmer to access and manipulate the variable arguments passed to the function.

Syntax

The syntax for creating a variadic function in C is as follows:

return_type function_name(type1 arg1, type2 arg2, ..., typeN argN, ...)
{
/* Function Bpdy */
}

The ellipsis (...) in the function parameter list is used to indicate that the function can take a variable number of arguments of any type. The types and names of the first N arguments are specified as usual, while the variable number of arguments are accessed using the va_list, va_start, va_arg, and va_end macros.

Built-in Variadic Functions

Printf

One of the most commonly used built-in variadic functions in C is the printf function. The printf function allows us to print a formatted string to the console, and it can take a variable number of arguments depending on the format specifiers used in the string passed to the function.

For example, the following code demonstrates the use of printf function to print a string, an integer, and a floating-point number:

#include <stdio.h>

int main()
{
int age = 30;
float pi = 3.14;

printf("My name is John and I am %d years old.
The value of pi is approximately %.2f.", age, pi);
return 0;
}

Output:

My name is John and I am 30 years old. The value of pi is approximately 3.14.

As shown in the example, the printf function is passed a string that contains two format specifiers: %d and %.2f. These specifiers indicate that the next argument passed to the function should be an integer and a floating-point number respectively. The printf function then replaces the format specifiers with the corresponding values of the variables age and pi. This allows us to easily print a string with dynamic values in a clean and readable format.

Scanf

Another most commonly used built-in variadic functions in C is the scanf function. This function can be used to read input from the user and store it in a variable of a specified data type.

Here is an example of how the scanf function can be used:

#include <stdio.h>

int main()
{
int age;

printf("Please enter your age: ");
scanf("%d", &age);
printf("Your age is: %d\n", age);
return 0;
}

The output of this code would be:

Please enter your age: 30
Your age is: 30

In this example, the scanf function is used to read an integer from the user and store it in the “age” variable. The “%d” is a format specifier that tells the function to expect an integer as input. The “&” symbol is used to pass the address of the variable to the function so that the value entered by the user can be stored in it.

As we can see, the scanf function is a powerful tool for reading input from the user, and with the use of format specifiers, it can be used to read a variety of data types. This is the power of variadic functions, they can take any number of arguments and handle them accordingly.

Custom Variadic Functions

Creating custom variadic functions in C requires the use of four macros: va_list, va_start, va_arg, and va_end.

The va_list macro is used to declare a variable that will hold the list of arguments passed to the function. This variable is typically named args.

va_list args;

The va_start macro is used to initialize the va_list variable, and must be passed the last non-variadic argument of the function.

va_start(args, last_non_variadic_arg);

The va_arg macro is used to retrieve the next argument from the va_list. It must be passed the va_list variable, and the type of the argument being retrieved.

int next_arg = va_arg(args, int);

Finally, the va_end macro must be called to clean up the va_list variable after all arguments have been retrieved.

va_end(args);

Using these macros, we can create a custom variadic function that can handle a variable number of arguments.

PC: Here

For example, a function that calculates the sum of a variable number of integers:

int sum_variadic(int count, ...)
{
va_list args;

va_start(args, count);
int sum = 0;
for (int i = 0; i < count; i++)
{
sum += va_arg(args, int);
}
va_end(args);
return sum;
}

This function can be called with any number of integer arguments, and will calculate their sum. For example:

int result = sum_variadic(3, 1, 2, 3);
printf("The sum is: %d", result);

Output:

The sum is: 6

It is important to note that the va_list, va_start, va_arg, and va_end macros are defined in the <stdarg.h> header file, which must be included in the program for the above code to work.

Practical Implementation

Example of variadic functions implementation to print strings:

#include <stdarg.h>
#include <stdio.h>

/**
* print_strings - Function to print strings
* @separator: String separator
* @n: number of strings
*
* Return: Formatted string
*/

void print_strings(const char *separator, const unsigned int n, ...)
{
unsigned int i;
char *str;
va_list vsprint;

va_start(vsprint, n);

for (i = 0; i < n; i++)
{
str = va_arg(vsprint, char *);

if (separator != NULL && i > 0)
{
printf("%s", separator);
}

if (str == NULL)
{
printf("(nil)");
}
else
{
printf("%s", str);
}
}

va_end(vsprint);
putchar(10);
}

int main(void)
{
print_strings(", ", 2, "Jay", "Django");
return (0);
}

The output of the above code will be:

Jay, Django

The function starts by initializing a va_list variable vsprint using the va_start macro, and passing the last non-variadic argument n as the parameter. Then, it enters a for loop that runs n times. In each iteration of the loop, the function uses the va_argmacro to extract the next argument from the va_list, which it assigns to the char pointer str.

If the separator is not null and the iterator is greater than 0, the function prints the separator. If the str pointer is null, the function prints (nil) otherwise it prints the string.

After the loop, the function uses the va_end macro to clean up the va_list. Finally, it prints a new line and exits the function.

In conclusion, this blog post has explored the intricacies of variadic functions in C programming language. We have examined the functionality of built-in variadic functions such as printf and scanf, and explored how to effectively utilize them in our code.

Additionally, we delved into the process of creating custom variadic functions using the va_list, va_start, va_arg, and va_end macros, and learned how to manage a variable number of arguments passed to the function.

Real-world use cases for variadic functions were also discussed, such as determining the sum of an undetermined number of integers or displaying a variable number of strings to the console. Through the use of examples and clear explanations, we hope to have imparted a comprehensive understanding of variadic functions and their potential for enhancing the functionality of our code.

Thanks for reading!

--

--

Samuel Selasi
Samuel Selasi

Written by Samuel Selasi

Software Engineer || Graphic Designer

Responses (2)