Tuesday, September 17, 2013

va_list and variadic function



C: Ellipsis operator (…) : printf

refer to: http://linuxprograms.wordpress.com/2008/03/07/c-ellipsis-operator-printf/

Ever imagined how printf works, even though we are able to pass a number of arguments to it. If we design a function which takes two arguments and pass three parameters, we are bound to get this error “too many arguments to function”i.e., suppose we have a function
    int fun2(int a, int b)
and we call the function
    fun2(2,3,4)
we are sure to get the above error. So the question is how printf / scanf works with variable number of arguments? This is because C has a feature called ellipsis (…) by which you are able to pass variable number of arguments?
So the prototype of printf is
    int printf(const char *str,...)
But the next question is how then can we access the arguments in the function. This can be done by the power of pointers. Let’s take a pointer which points to the last argument before …
and depending on the next arguments of what we expect, we increment the pointer and increment it accordingly
Below is a simple code which shows how this can be done
int print(const char *str,...)

/*str has the number of integers passed*/

{

        int i;

        int num_count=atoi(str);

        int *num=(int *)&str;

        for(i=1;i<=num_count;i++)

                printf("%d ",*(num+i));}

int print_num(int num_count,...)

/*num_count contains the number of integers passed*/

{

        int i;

        int *num=&num_count;

        for(i=1;i<=num_count;i++)

                printf("%d ",*(num+i));

}

int main()

{

        print_num(3,2,3,4);

        print("3",2,3,4);

}
Here, I explained how we can utilize the operator ellipsis (…) to pass variable number of arguments to a function. I have utilised there the concept of pointers to access the variable arguments. The standard C Library provides support to access these arguments. Use for this support
All you need is to know the last argument before the ellipsis operator(At least one argument is must to use variable arguments), let’s call it larg
suppose
    fun(type var1,type var2,...)
is a function, then larg corresponds to var2
Now we need to declare the list using va_list
i.e.,
    va_list al
now initialize it using va_start
    va_start(al,larg);
Now to access each argument, we must know the expected type of the argument
     type var_name = va_arg(al,type);
When we have accessed all the variable arguments, we need to clean up
     va_end(al);
Using standard library, we can easily access the variable arguments
Take a simple example
#include <stdarg.h>
int print(int num_count,...)
/*num_count contains the number of integers passed*/
{
  int i;
  va_list al;
  va_start(al,num_count);
  for(i=1;i<=num_count;i++){
     int val=va_arg(al,int);
     printf("%d ",val);
  }

}

int print_str(const char *str,...)
/*str has the number of strings passed*/
{
  int i;
  va_list al;
  int num_count=atoi(str);
  va_start(al,str);
  int *num=&num_count;
  for(i=1;i<=num_count;i++){
     char *str=va_arg(al,char *);
     printf("%s ",str);
  }

}

int main()
{
   print(3,2,3,4);
   print_str("3","Hi","All","!!!");
}
OUTPUT
2 3 4 Hi All !!!

No comments:

Post a Comment