I have a function foo(char *n, ...);
I need to get and use all of optional char
parameters.
I had an idea to use
while(va_arg(argP
There is no direct way for a function that uses va_arg
to determine the number or type(s) of the arguments passed by a given call.
Your proposed method in particular:
while(va_arg(argPtr, char) != NULL)
is incorrect. va_arg(argPtr, char)
yields a value of type char
, while NULL
is a null pointer constant. (NULL
is commonly defined as 0
, which compares equal to the null character '\0'
, but you can't rely on that.)
Any variadic function must have a way for the caller to specify the number and types of arguments. The *printf
functions, for example, do so via the (non-variadic) format string. The POSIX execl*()
functions expect a sequence of char*
arguments; the end of the argument list is marked by the caller with (char*)NULL
. Other methods are possible, but they almost all depend on information given at run time in the arguments. (You could use some other method, such as a global variable. Please don't.)
This places a burden on the caller to ensure that the arguments passed to the function are consistent. The function itself has no way to confirm this. Incorrect calls, like printf("%d\n", "hello")
or execlp("name", "arg1")
have undefined behavior.
One more thing: you can't use va_arg
with an argument of type char
. When you call a variadic function, arguments corresponding to the , ...
are promoted. Integer arguments of types narrower than int
are promoted to int
or to unsigned int
, and arguments of type float
are promoted to double
. If a caller passes an argument of type char
, the function must invoke va_arg(argPtr, int)
.
(In very obscure circumstances that you're not likely to run into, char
can be promoted to unsigned int
. That can happen only if plain char
is unsigned and sizeof (int) == 1
, which implies that a byte is at least 16 bits.)
The basic idea would work. But you've filled in the details in a way that almost certainly won't.
The usual implicit conversion rules don't apply when you're using variadic arguments. Instead, default argument promotions take place, which means that any integer type smaller than int
/unsigned int
gets converted to one of those -- that's not the only promotion, but the only one relevant here -- and which also means that there is no automatic conversion to whatever type you specify with va_arg
.
This means that:
va_arg(..., char)
, since it's impossible to pass a char
as a variadic function argument.NULL
as a variadic function argument, since its concrete type is heavily implementation-dependent. Realistic types are int
, long
, void *
, and there are loads of other less realistic but equally valid types.You could change
while(va_arg(argPtr, char) != NULL)
to
while(va_arg(argPtr, int) != 0)
and the call
foo(n, 't', 'm', '$', NULL);
to
foo(n, 't', 'm', '$', 0);