Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2054
  • Last Modified:

Function with unlimited arguments???

Hi all,
I want to know that how is it possible to have a function that can be called with a variable number of argument of a specific type,
for example:
f1(12,13,24);
f1(12,32,43,43,34);
and there is no idea about number of argument so overloading seems to be useless

thanx in advance...
0
Farzad_6e
Asked:
Farzad_6e
2 Solutions
 
AlexFMCommented:
Writing of function with variable number of arguments is not safe and requires some agreements between caller and function. For example, first argument may be number of arguments of the function. Incorrect call effectively crashes a program, as we can see using, for example, scanf.

Take a look at va_arg, va_end and va_start macros. Appropriate MSDN topic shows example of function with variable number of arguments:

// -1 is used as terminator
printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );


int average( int first, ... )
{
   int count = 0, sum = 0, i = first;
   va_list marker;

   va_start( marker, first );     /* Initialize variable arguments. */
   while( i != -1 )
   {
      sum += i;
      count++;
      i = va_arg( marker, int);
   }
   va_end( marker );              /* Reset variable arguments.      */
   return( sum ? (sum / count) : 0 );
}

0
 
AlexFMCommented:
UNIX-compatible version of the same function:

int average( va_alist )
va_dcl
{
   int i, count, sum;
   va_list marker;

   va_start( marker );            /* Initialize variable arguments. */
   for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )
      sum += i;
   va_end( marker );              /* Reset variable arguments.      */
   return( sum ? (sum / count) : 0 );
}
0
 
nietodCommented:
>> Writing of function with variable number of arguments is not safe and requires some
>> agreements between caller and function. For example, first argument may be number
>> of arguments of the function. Incorrect call effectively crashes a program, as we can
>> see using, for example, scanf.
Agreed!   VA (Variable argument) functions are one of the leading causes of bugs in C programs.  C++ and the STL were developed in part to prevent these bugs by eliminating the need for VA functions.   So I really think you should reconsider using VA functions.  C++ provides many alternative techniques that elminate the need for resorting to VA.  We might be able to sugest some if you coudl explain what it is you are trying to do.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
SalteCommented:
This is possible but the problem is to find out when to stop reading arguments.

This is done in one of two ways:

a) Having a "stop value" to indicate when there are no arguments.

For example you can write a concat function which concatenates a number of strings and allocates them on heap:

char * concat(const char * s, ...)
{
   va_list v;
   // first go through the arguments to find the length
   // of all the strings.
   size_t len = 0;
   const char * t;
   if (s != 0) {
      len = strlen(s);
      va_start(v,s);
      t = va_arg(v,const char *);
      while (t != 0) {
         len += strlen(t);
         t = va_arg(v,const char *);
      }
      va_end(v);
   }
   char * dst = new char[len + 1];
   if (s != 0) {
      strcpy(dst,s);
      va_start(v,s);
      size_t x = strlen(s);
      t = va_arg(v,const char *);
      while (t != 0) {
         strcpy(dst + x,t);
         x += strlen(t);
         t = va_arg(v,const char *);
      }
      va_end(v);
   }
   dst[len] = 0;
   return dst;
}

This function can be called like this:

char * s = concat("hello"," ","there",0);

It stops when you give a 0 pointer argument.

You must specify a 0 value as the last argument to any call to this function, if you do not it will just continue to read garbage until that garbage happen to have the value of a NULL pointer.

Also, you can't give 0 arguments, if you want to allow for concat() giving an empty string out you must specify that as an extra overload:

char * concat()
{
   char * d = new char[1];
   *d = 0;
   return d;
}

The other way is to provide a first argument that give info about how many arguments that follows and possibly also their type. This is the way that printf() does. For example a poly function computing polynomials can be made like this:

poly(2,5,1,-3,2); // compute 1 * 5 * 5 - 3 * 5 + 2

poly(n,x,c[n],c[n-1],c[n-2],....c[1],c[0]);

compute c[n]*pow(x,n) + c[n-1]*pow(x,n-1)...etc..

so poly(n,x,cn,...c0) == poly(n-1,x,cn,....,c1)*x + c0

double poly(int n, double x, ...)
{
   va_list v;
   double res = 0;

   va_start(v,x);
   for (int i = 0; i <= n; ++i) {
      double c = va_arg(v,double);
      res = x * res + c;
   }
   va_end(v);
   return res;
}

a function like printf also indicate the type of the element so you need to decode the format argument and if it indicate 'int' you do va_arg(v,int) etc.

Alf
0
 
HermeticCommented:
One solution might be to use an array and count. like this
func(int CountofElements, int *ArgArray);
It requires that you trust the caller only slightly less than the VA situation.
0
 
SalteCommented:
The reason why VA is not safe is that it is perfectly possible to do mistakes, referring to my two methods of providing VA arguments above.

If you have a 'stop value' you can simply call the function without having the stop value at the end.

concat("hello ", "there");

will crash.


The other method you can give fewer or more arguments than your info argument indicate. If the poly is called like this:


poly(15, 0.5, 2, 3, 7);

it will crash, similarly:

poly(3, 0.5, 2, 3, 7, 11, 19);

This will compute f(x) with x = 0.5 for
2 * x*x*x + 3*x*x + 7*x + 11. The argument 19 is not read or used.

A similar situation occur in method 1 above if you provide arguments after the stop-value:

concat("hello, ", 0, "how are you?");

will only return a string containing "hello, ", the "how are you?" part is never read or used.

Avoiding va args eliminate these problems. However, this elmination isn't really very true. The problem is that the only other way to provide a variable number of arguments to one single function call is to provide an array and using that array you can lie about the size of it, it is also more troublesome to set up an array so it doesn't really solve it.

This leaves you to using a set of functions to provide the functionality and in this C++ provide a very good mechanism as shown by iostream. Creating an object and then "stuff" values into that object can

1. Preserve type of the value.
2. Preserve the number of values.
3. is safe.

Then providing that object as argument to your function will the process the values as you should.

For example a concat using this method is easy to write using stringstream:

stringstream ss;
ss << "string one";
ss << "string two";
...

ss.c_str() is now the concatenated string.

Similar method for printf is found in the boost formatter library where you create a format class with format and then give it values in a similar manner.

Using overloads you also get it so that you can remember the type of the value provided etc and you can use type specific overloads for using the value.

However, if you don't want to use this technique, then I doubt that using arrays is any safer than va_args, giving an array and saying it has 10 elements is just as bad as calling a VA function with the wrong setup. I would think it is also just as easy to make both those mistakes because they are fundamentally the same error - mismatch between how the function call should be and how it is.

Alf
0
 
tinchosCommented:
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Split Points between AlexFM & Salte

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Tinchos
EE Cleanup Volunteer
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now