2

Possible Duplicates:
C++ preprocessor __VA_ARGS__ number of arguments
How to count the number of arguments passed to a function that accepts a variable number of arguments?

To learn variable parameter function, I write a demo:

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

int foo(int n, int m, ...);

int
main (int argc, char *argv[])
{
    int n = 10;
    int m = 15;
    int p = 20;
    //foo (n, m);
    foo(n, m, 20);

    return EXIT_SUCCESS;
}

int foo (int n, int m, ...)
{
    va_list ap;
    int p;
    char *str;

    va_start (ap, m);
    p = va_arg (ap, int);
    n = m + p;
    printf ("%d.\n", n);
    va_end (ap);
    return 0;
}

I want to know how to deal with the function if it has only two parameters. (For this demo, if only n and m, after running foo, I want to get result: n = n+m.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vincent Zhang
  • 97
  • 1
  • 6

4 Answers4

1

For every variable argument ('variadic') function, there has to be a way for the function to know how many arguments it must process. There are various ways of handling that.

  • The printf() and scanf() families of functions use the format string to determine how many arguments are passed to the function.
  • The POSIX open() function looks at the options in the second argument to know whether there is a third argument.
  • The POSIX execl() function scans until it comes across a null pointer argument.
  • You can pass an explicit count of the number of arguments to process (see example by Fei Jiang).

All these methods work. The open() mechanism is the least general and most peculiar (arising mainly from historical quirks).

But one such mechanism must be used. The called function must be able to tell (somehow) when it has finished processing the variable section of its argument list.

Unless you are relaying the variable length argument list to other functions (e.g. you use vsnprintf() to format a string with the variable arguments passed to the function), your variadic function body will need a loop in it to process the variable number of arguments. Your function is missing that loop.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

At runtime, there is no way to know the actual number of additional parameters from va_list. Hence there should be another way to deduce this number, e.g. from previous parameters or from some end-of-list convention (as in, give any number of pointers followed by NULL). Consider printf, where the format string determines how many parameters (of what types) to expect in the va_list part.

As long as you take this into account, there would be nothing special about the minimum number of parameters (that is, empty va_list). Just don't pop anything from va_list when you know there is nothing to expect.

Anton Kovalenko
  • 20,999
  • 2
  • 37
  • 69
1

I do not understand what you want 'foo' to do, but typically foo should have a loop in it, and also foo should been told how many arguments it has been given when called, or rather, when the loop ends. printf knows this by %d %s %f ... in the first char* pattern parameter

For example, if we want to write a function that returns the sum of several integers, we can implement like this

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

int int_sum(int count, ...) {
    int sum = 0, i;
    va_list ap;
    va_start(ap, count);
    for (i = 0; i < count; ++i) {
        sum += va_arg(ap, int);
    }
    va_end(ap);
    return sum;
}

int main() {
    printf("%d\n", int_sum(5, 1, 2, 3, 4, 5));
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fei Jiang
  • 330
  • 1
  • 6
  • +1: Good point about the loop being necessary! And a count of the number of argument to process is one of a number of possible techniques for determining how many arguments were passed to the function. – Jonathan Leffler Jan 04 '13 at 16:04
  • I want to write a node-insert function like this: node_insert (list, new), node_insert (list, new_elem, pos) if it is with 2 arg, it will insert node from header, if it with 3 arg, it will insert node at the position where the node's elem == pos. – Vincent Zhang Jan 04 '13 at 16:37
  • @VincentZhang It is not proper to use variable-parameter functions in such situation. – Fei Jiang Jan 04 '13 at 16:44
  • @Fei Jing: New to C, just for exercising. And what mathod should be? – Vincent Zhang Jan 04 '13 at 16:53
  • @VincentZhang The only difference between these two is, when calling the 3-para one, the caller pushes another one integer(that is, pos) before new_elem on the runtime stack, but your could not tell the integer upon new_elem is the third parameter of node_insert or a local variable of the caller. The only method I could come up with is, add extra information, i.e. another parameter indicating which form do you really call, but obviously, it's a bad design – Fei Jiang Jan 04 '13 at 17:14
0

I am not sure if I understood the question, but if you have only a single argument in a varlist function, e.g. foo (int n,...), followed by ..., then you can pass the first argument of foo (n in our case) in va_start(), and it will always work.

int foo (int n,  ...);
int
main (int argc, char *argv[])
{
    int n = 10;
    int m = 15;
    int p = 20;

    foo (n, m);
    //foo (n, m, 20);

    return EXIT_SUCCESS;
}

int foo (int n,  ...)
{
    va_list ap;
    int p;
    char *str;

    va_start (ap, n);
    p = va_arg (ap, int);
    n = n + p;
    printf ("%d.\n", n);
    va_end (ap);
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rajneesh
  • 1,709
  • 1
  • 13
  • 13