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.)

1
  • 1
    @RedX: That dupe is for variadic macros, not variadic functions. Commented Jan 4, 2013 at 15:47

4 Answers 4

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

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

5 Comments

+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.
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.
@VincentZhang It is not proper to use variable-parameter functions in such situation.
@Fei Jing: New to C, just for exercising. And what mathod should be?
@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
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;
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.