C/C++ – Variable number of arguments to a function

Ever wondered how printf() in C would be implemented ? If you are a C-lover, I guess you would have, for its a function that looks pretty different from the other library functions, consumes tons of options and its very powerful. If you are not a C-fan and do not know much of it, you may want to have a look here . Well, one of the great flexibility of printf() comes from the fact that it can consume variable number of arguments. If you are scratching your head about how it does that, hold on,  you will know it in a minute. That is what this post aims at 🙂 . Lets look at some examples to understand what ‘variable number of arguments’ means.


#include<stdio.h>
int main()
{
   char * string = "with";
   printf("printf with 1 arguement\n");
   printf("Printf with %d arguements\n", 2);
   printf("Printf %s %d arguements", string, 3);
   return 0;
}

Note that the first version takes one argument, the second version takes two arguments and the third takes three. Have you ever written a function definition in C that can be invoked with any number of arguements 1…N ? If not, lets write one. But on the way we need to learn a couple of things as ingredients to it. We need to know of four simple things. The definitions have been taken from cplusplus.com. If you dont understand what they mean, you may first want to see how they are used ( see the code below) and believe me, its very simple to understand them from the usage.

  1. va_list:  Type to hold information about variable arguments.

     Objects of this type can only be used as argument for the  va_start,  va_arg,  va_end and  va_copy macros, or functions that use them, like the variable argument functions in <cstdio>  (vprintf,  vscanf,  vsnprintfvsprintf and  vsscanf).

  2. void va_start (va_list ap, paramN)

    Initialize a variable argument list. Initializes ap to point to the first unnamed argument. It retrieve the additional arguments after parameter paramN. A function that invokes va_start(), should also invoke va_end() before it returns.

  3. type va_arg (va_list ap, type)
    Retrieve next argument. This macro expands to an expression of type type with the value of the current argument in the variable arguments list identified by ap.
  4. void va_end (va_list ap);
    Each invocation of va_start() must be matched by a corresponding invocation of va_end() in the same function.. It performs the appropriate actions to facilitate a normal return by a function that has used the va_list object ap .

Pheww thats a lot of technical Jargon !! Lets revert to some simpler words now. In short, you need to first define a list of type va_list by saying something like.. va_list args. Next, invoke a call to va_start() to indicate where the variable list of arguments  starts from, extract each argument from the variable list (args in our case) using va_arg() and finally dont forget calling va_end().

Note that apart from va_ag(), a va_list object (named ap in declarations below ) can also be consumed by versions of printf() that are preceded by ‘v’, for example:

  1. int vprintf ( const char * format, va_list ap ); – Prints formatted data from variable argument list to stdout,
  2. int vfprintf ( FILE * stream, const char * format, va_list ap ); – Writes formatted data from variable argument list to stream and
  3. int vsprintf (char * s, const char * format, va_list ap ); – Writes formatted data from variable argument list to string s.

Lets look at an example that uses the a va_arg(). For the above mentioned printf versions, you can find a C program for each of the 3 functions listed above in the links in the “References” section  (#2, #3, #4 respectively) at the end of this post.

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

/* The sum() function can accept variable number of arguments.
   In the function declaration ... means that the number and
   type of the arguments may vary. The marker ... can only
   appear at the end.
*/
int sum(int num_of_arguments, ... )
{
  /* A list to store the aruements. In example, this may contain
    1,2,3 and 4 elements on successive calls from main()
  */
  va_list args;
  int sum= 0, i;

  /* Directing the va_list args initialized above to start storing
     all parameters folloowing the first parameter 'num_of_arguments'
  */
  va_start (args, num_of_arguments );

  /* Loop until all parameters are seen. */
  for (i= 0; i< num_of_arguments; i++ )
  /* Extract the next value in argument list and add it to sum. */
  sum += va_arg (args,int);

  /* Signal that we are done with our usage of the list */
  va_end (args);

  return sum;  /* Returns the calculated sum.*/
}
int main()
{
  int result;

  result=sum (1,1);
  printf("result of sum() with 2 arguement: %d \n", result);

  result=sum (2,1,2);
  printf("result of sum() with 3 arguement: %d \n", result);

  result=sum (3,1,2,3);
  printf("result of sum() with 4 arguement: %d \n", result);

  result=sum (4,1,2,3,4);
  printf("result of sum() with 5 arguement: %d \n", result);

  return 0;
}

Time to see what the function outputs. Here you go:

result of sum() with 2 arguement: 1 
result of sum() with 3 arguement: 3 
result of sum() with 4 arguement: 6 
result of sum() with 5 arguement: 10

And as always play with the above  code on ideone. Change a few things here and there and see how it works. Done with this? Lets try and implement our own version of printf().

References:

  1. Linux man page: http://linux.die.net/man/3/va_arg
  2. http://www.cplusplus.com/reference/cstdio/vprintf/
  3. http://www.cplusplus.com/reference/cstdio/vfprintf/
  4. http://www.cplusplus.com/reference/cstdio/vsprintf/

About Shiv

I am passionate about Software Development and I have always had a dream of developing a software from scratch to its completion in all respects. I am a CS grad from BIT mesra, having done BE(IT). I love designing, coding etc and to enhance my problem solving skills I practice questions at uvaonlinejudge.org, hackerrank, projecteuler, codeforces.com etc. I love to share my experiences be it coding , cricket , tech talk or others . Use "categories" section to chose what you like !!! Any corrections/suggestions are welcome.

Posted on May 18, 2013, in Coding, Some Beautiful Codes. Bookmark the permalink. 1 Comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: