Spread the love

This is the question asked to me in my HCL interview “How can I write a function that takes a variable number of arguments?” after the answering this they start cross questioning on this like “What are the limitations with this?” ,” What is vprintf()?”, etc. So i have decided to make a nice post on this topic.

Introduction

                    stdarg.h is a header file in the C standard library of the C programming language that allows functions to accept an indefinite number of arguments. It provides facilities for stepping through a list of function arguments of unknown number and type. C++ provides this functionality in the header cstdarg.

                    All functions like printf(), scanf() etc use this functionality. The program below uses this library and its functions to implement variadic function. 

                    Variadic functions are functions which may take a variable number of arguments and are declared with an ellipsis in place of the last parameter. A typical declaration is

 

int check(int a, double b, ...);

 

Example

 

#include <stdio.h>
#include <stdarg.h>
 
// Add all the arguments and return sum  untill zero(0) appear
int SumArgs(int first_arg, ...)
{
	int i,sum=0;
	
	va_list args;
	va_start(args, first_arg); 
	
	for (i = first_arg; i > 0; i = va_arg(args, int))
	{
		sum+=i;
	}
	
	va_end(args);
	
	return sum;
}
 
int main(void)
{
   printf("%d",SumArgs(10,10,10,0));

   return 0;
}

 

Explanation

There is only three things unknown here, which is va_list, va_start( ), va_arg( ) and va_end( ). Let we understand them one by one

va_list

 

va_list args;

 

This line declares a variable, args, which we use to manipulating the argument list containing variable arguments of our function. The data type of the variable is va_list, a special type defined by <stdarg.h>.

va_start( ) 

 

va_start(args, first_arg);

 

This line initializes args variable with function’s last fixed argument i.e. first_arg. va_start() uses this to figure out from where the variable arguments begin.

va_arg( ) 

 

i = va_arg(args, int)

 

va_arg() fetches the next argument from the argument list. The second parameter to va_arg() is the data type of the argument we expect. 

Note: va_arg( ) function will never receive arguments of type char, short int, or float. va_arg( ) function only accept arguments of type char *, unsigned int, int or double.

va_end( ) 

 

va_end(args);

 

Finally, when we’re finished processing the all arguments, we call va_end(), which performs any necessary cleanup.

Limitations of variable arguments function

How can I find how many arguments a function was passed?

Any function which takes a variable number of arguments must be able to determine from the arguments themselves, how many of them there have been passed. printf() and some similar functions achieve this by looking for the format string. This is also why these functions fail badly if the format string does not match the argument list. Another common technique, applicable when the arguments are all of the same type, is to use a sentinel value (often 0, -1, or an appropriately-cast null pointer) at the end of the list. Also, one can pass an explicit count of the number of variable arguments. 

Is this allowed ? void function(…..)

No! Standard C requires at least one fixed argument, in part so that you can hand it to va_start().

How do I get floating point numbers passed as arguments?

Arguments of type float are always promoted to type double, and types char and short int are promoted to int.

Therefore, it is never correct to invoke

 

va_arg(args, float);

 

instead you should always use

va_arg(args, double);

 

Similarly, use

va_arg(args, int);

 

to retrieve arguments which were originally char, short, or int.

What is the use of vprintf(), vfprintf() and vsprintf()?

Below, the myerror() function prints an error message, preceded by the string “error: ” and terminated with a newline:

 

void myerror(char *fmt, ...)
{
	va_list argp; fprintf(stderr, "error: ");
	
	va_start(argp, fmt);
	
	vfprintf(stderr, fmt, argp);
	
	va_end(argp);
	
	fprintf(stderr, "\n");
}

 

Sources

  1. http://en.wikipedia.org/wiki/Stdarg.h
  2. http://www.eskimo.com/

Suggested Reading

  1. Functions that are executed before and after main( )
  2. Write your own printf() function