Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable number of arguments in C programmng

Whenever we use variable argument function in C language, we have to provide the total number of arguments as the first parameter. Is there any way in which we can make a function with variable arguments without giving the total number of arguments?


[update from comment:]

I want to use functions like sum(1,2,3) should return 6. i.e, no counter should be there.

like image 458
Shubham Kumar Avatar asked Oct 05 '18 10:10

Shubham Kumar


3 Answers

Several ways:

  • pass simple, explicit count (which you don't want in this question)
  • pass some format string, similar to printf and scanf
  • pass some "mode" parameter, and have each mode require specific varargs
  • have all varargs to be of same type, and require last argument to be some special value, AKA sentinel value, such as NULL for pointer list or max/min value of the type for integer types, or NaN for doubles.

However you do it, you have to have some way for the function to know the types of the varargs, as well as a way for it to know when they end. There is no built-in way in C, argument count is not passed to the function.

like image 131
hyde Avatar answered Sep 18 '22 09:09

hyde


I want to use functions like sum(1,2,3) should return 6. i.e, no counter should be there

You could define a sentinel. In this case 0 might make sense.

/* Sums up as many int as required. 
   Stops adding when seeing the 1st 0. */
int sum(int i, ...)
{
  int s = i;

  if (s)
  {
    va_list ap;

    va_start(ap, i); 

    /* Pull the next int from the parameter list and if it is
       equal 0 leave the while-loop: */
    while ((i = va_arg(ap, int))) 
    {
      s += i;
    }

    va_end(ap);
  }

  return s;
}

Call it like this:

int sum(int i, ...);

int main(void)
{
   int s = sum(0); /* Gives 0. */

   s = sum(1, 2, 3, 0); /* Gives 6. */
   s = sum(-2, -1, 1, 2, 0); /* Gives 0. */
   s = sum(1, 2, 3, 0, 4, 5, 6); /* Gives 6. */

   s = sum(42); /* Gives undefined behaviour! */
}

The sum() function alternatively could also look like this (but would do one useless addition of 0):

/* Sums up as many int as required. 
   Stops adding when seeing the 1st 0. */
int sum(int i, ...)
{
  int s = i;

  if (s)
  {
    va_list ap;

    va_start(ap, i); 

    /* Pull the next int from the parameter list and if it is
       equal 0 leave the do-loop: */
    do
    {
      i = va_arg(ap, int);
      s += i;
    } while (i);

    va_end(ap);
  }

  return s;
}
like image 23
alk Avatar answered Sep 20 '22 09:09

alk


You don't have to supply that number of arguments. For instance, consider the signature for printf:

int printf( const char* format, ... );

It "finds out" how many arguments it needs by parsing the string you give it. Of course, your function needs to know the amount of arguments in some way, otherwise what sense does it make for it to take a variable number of arguments?

like image 27
Blaze Avatar answered Sep 20 '22 09:09

Blaze