You don’t have to do anything special to call a variadic function. Just put the arguments (required arguments, followed by optional ones) inside parentheses, separated by commas, as usual. But you must declare the function with a prototype and know how the argument values are converted.
In principle, functions that are defined to be variadic must also be declared to be variadic using a function prototype whenever you call them. (See Variadic Prototypes, for how.) This is because some C compilers use a different calling convention to pass the same set of argument values to a function depending on whether that function takes variable arguments or fixed arguments.
In practice, the GNU C compiler always passes a given set of argument
types in the same way regardless of whether they are optional or
required. So, as long as the argument types are self-promoting, you can
safely omit declaring them. Usually it is a good idea to declare the
argument types for variadic functions, and indeed for all functions.
But there are a few functions which it is extremely convenient not to
have to declare as variadic—for example,
Since the prototype doesn’t specify types for optional arguments, in a
call to a variadic function the default argument promotions are
performed on the optional argument values. This means the objects of
short int (whether signed or not) are
promoted to either
unsigned int, as
appropriate; and that objects of type
float are promoted to type
double. So, if the caller passes a
char as an optional
argument, it is promoted to an
int, and the function can access
va_arg (ap, int).
Conversion of the required arguments is controlled by the function prototype in the usual way: the argument expression is converted to the declared argument type as if it were being assigned to a variable of that type.