Variable Number of Arguments in C++

Passing variable number of arguments around

To pass the ellipses on, you initialize a va_list as usual and simply pass it to your second function. You don't use va_arg(). Specifically;

void format_string(char *fmt,va_list argptr, char *formatted_string);


void debug_print(int dbg_lvl, char *fmt, ...)
{
char formatted_string[MAX_FMT_SIZE];

va_list argptr;
va_start(argptr,fmt);
format_string(fmt, argptr, formatted_string);
va_end(argptr);
fprintf(stdout, "%s",formatted_string);
}

Variable number of arguments in C programmng

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;
}

Variable number of Arguments in C? [duplicate]

int ff(int num, ...)
{
va_list arguments;
int sum = 0;
va_start(arguments, num);
for (int x = 0; x < num; x++)
{
sum += va_arg(arguments, int);
}
va_end(arguments);

return sum;
}

//call
printf("%d\n", ff(3, 1, 2, 3));

va_list contains list of arguments in ..., in loop you get access one by one va_arg(arguments, int);

Variable number of arguments in C++?

You probably shouldn't, and you can probably do what you want to do in a safer and simpler way. Technically to use variable number of arguments in C you include stdarg.h. From that you'll get the va_list type as well as three functions that operate on it called va_start(), va_arg() and va_end().

#include<stdarg.h>

int maxof(int n_args, ...)
{
va_list ap;
va_start(ap, n_args);
int max = va_arg(ap, int);
for(int i = 2; i <= n_args; i++) {
int a = va_arg(ap, int);
if(a > max) max = a;
}
va_end(ap);
return max;
}

If you ask me, this is a mess. It looks bad, it's unsafe, and it's full of technical details that have nothing to do with what you're conceptually trying to achieve. Instead, consider using overloading or inheritance/polymorphism, builder pattern (as in operator<<() in streams) or default arguments etc. These are all safer: the compiler gets to know more about what you're trying to do so there are more occasions it can stop you before you blow your leg off.

Clarification of requirements for variable arguments in c program

The main rule regarding a variadic function is that you need some way of determining how many arguments you have and what the type of those arguments are, though not necessarily the way the tutorial say.

Generally, there are two ways: either one of the fixed arguments tells you the number and possibly the type of the variadic arguments, or one of the variadic arguments is a sentinel value which specifies the end of the argument list.

Examples from the standard library and POSIX:

  • printf and family: The first argument is a format string, and the contents of this format string specify the number and type of each variadic argument.
  • execl: The second of its two fixed arguments is the first argument of an external program to run. If it is not NULL, variadic arguments are read as type const char * until it finds one that is NULL.

A variation of the first option is as you mentioned: one of the fixed arguments is the number of variadic arguments, where each variadic argument has the same predetermined type. This is the simplest to implement, which is probably why the tutorial you linked suggested it.

Which of these you choose depends entirely on your use case.

Another interesting variation is the open function on Linux and similar systems. The man pages show the following signatures:

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

The actual declaration looks something like this:

extern int open (const char *__file, int __oflag, ...) __nonnull ((1));

In this case, one variadic argument is read if the flags parameter includes the value O_CREAT.

How to count the number of arguments passed to a function that accepts a variable number of arguments?

You can't. You have to manage for the caller to indicate the number of arguments somehow. You can:

  • Pass the number of arguments as the first variable
  • Require the last variable argument to be null, zero or whatever
  • Have the first argument describe what is expected (eg. the printf format string dictates what arguments should follow)

Functions with variable number of arguments c

If you want to do it yourself, you need to look at the source code of the C runtime library and see what it does when you access the arguments. Or what the generated inline code does, if the compiler inlines this. Use https://godbolt.org to easily see what code gets generated. This is also a matter of a documented ABI on both ARM and x86-64 targets, so you can read there how the arguments get passed to variadic functions.

In general, by using char* you’re ignoring the ABI-mandated alignment of arguments on the stack. In C++ you’d want char alignas(void*)* in most cases, but even then this sort of manipulation is undefined behavior so you’re writing brittle and unportable code.

When you implement it properly using the standard variadic argument support, your code will be portable among a multitude of architectures, even small 8- and 16-bit microcontrollers. I’ve just checked and the code then works on Zilog’s eZ8 (an 8-bit system with 16-bit far pointers) and on Zilog ZNEO (a 16-bit system with 24-bit pointers and 32-bit integers), and that’s on Zilog’s own C compiler, not gcc. I’ve checked that it works on both hardware and on the simulator in the IDE.

How do i make a function with a variable number of parameters?

First of all Variadic arguments from C are considered a bad practice in C++ and should be avoided.

There are plenty of better C++ solutions which are able to replace this C feature.

Old fashioned std::vector:

std::vector<int> filterPrimes(std::vector<int> a) {
auto end = std::remove_if(a.begin(), a.end(), [](auto x) {
return !isPrime(x)
};
a.remove(end, a.end());
return a;
}

Or std::initializer_list

std::vector<int> filterPrimes(std::initializer_list<int> l) {
std::vector<int> r;
std::copy_if(l.begin(), l.end(), std::back_inserter(r), isPrime);
return r;
}

Or Variadic templates, or template with iterator ranges, or ... .



Related Topics



Leave a reply



Submit