Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standard way of determining the number of va_args?

I'm experimenting with variable arguments in C++, using va_args. The idea is useful, and is indeed something I've used a lot in C# via the params functionality. One thing that frustrates me is the following excerpt regarding va_args, above:

Notice also that va_arg does not determine either whether the retrieved argument is the last argument passed to the function (or even if it is an element past the end of that list).

I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself. I would like to perform something like the following:

void fcn(int arg1 ...)
{
    va_list argList;
    va_start(argList, arg1);

    int numRemainingParams = //function that returns number of remaining parameters
    for (int i=0; i<numRemainingParams; ++i)
    {
        //do stuff with params
    }
    va_end(argList);
}

To reiterate, the documentation above suggests that va_arg doesn't determine whether the retrieved arg is the last in the list. But I feel this information must be accessible in some manner.

Is there a standard way of achieving this?

like image 868
Kirby Avatar asked Oct 15 '12 17:10

Kirby


People also ask

What is Va_args?

va_arg returns the value of the next argument in a varying-length argument list. The first argument, ap , is a work area of type va_list , which is used by the expansions of the various <stdarg. h> macros.

How many will accept a variable number of arguments?

There can be only one variable argument in a method. Variable argument (Varargs) must be the last argument.

What is variadic macro in C?

Variadic macro extensions refer to two extensions to C99 and Standard C++ related to macros with variable number of arguments. One extension is a mechanism for renaming the variable argument identifier from __VA_ARGS__ to a user-defined identifier.

How can you get the type of arguments passed to a function?

Passing Arguments There are two ways to pass arguments to a function: by reference or by value. Modifying an argument that's passed by reference is reflected globally, but modifying an argument that's passed by value is reflected only inside the function.


2 Answers

I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself.

Nonetheless, it is true. C/C++ do not put markers on the end of the argument list, so the called function really does not know how many arguments it is receiving. If you need to mark the end of the arguments, you must do so yourself by putting some kind of marker at the end of the list.

The called function also has no idea of the types or sizes of the arguments provided. That's why printf and friends force you to specify the precise datatype of the value to interpolate into the format string, and also why you can crash a program by calling printf with a bad format string.

Note that parameter passing is specified by the ABI for a particular platform, not by the C++/C standards. However, the ABI must allow the C++/C standards to be implementable. For example, an ABI might want to pass parameters in registers for efficiency, but it might not be possible to implement va_args easily in that case. So it's possible that arguments are also shadowed on the stack. In almost no case is the stack marked to show the end of the argument list, though, since the C++/C standards don't require this information to be made available, and it would therefore be unnecessary overhead.

like image 163
rici Avatar answered Sep 23 '22 15:09

rici


The way variable arguments work in C and C++ is relatively simple: the arguments are just pushed on the stack and it is the callee's responsibility to somewhat figure out what arguments there are. There is nothing in the standard which provides a way to determine the number of arguments. As a result, the number of arguments are determined by some context information, e.g., the number of elements referenced in a format string.

Individual compilers may know how many elements there are but there is no standard interface to obtain this value.

What you could do instead, however, is to use variadic templates: you can determine very detailed information on the arguments being passed to the function. The interface looks different and it may be necessary to channel the arguments into some sort of data structure but on the upside it would also work with types you cannot pass using variable arguments.

like image 24
Dietmar Kühl Avatar answered Sep 20 '22 15:09

Dietmar Kühl