The primary reason you need at least one named parameter in a variadic C function is that you
need some way to communicate the number of arguments and/or their data types. In functions
such as printf, the first argument, the format string, communicates the exact number and data
type of each of the remaining arguments.
Let’s say that all arguments passed to your function were always going to be the exact same,
known data type. You would still need to somehow tell the called function how many arguments
there were. A straightforward way of doing this would be to define the first (and required)
parameter as an integer, which the caller would supply as the correct count of subsequent
arguments.
Now, in this situation, you could choose a different approach. For example, you could decide to
use a sentinel value to signal the end of the argument list. This approach burns an otherwise
valid argument value, but that might be okay. In this situation, you don’t really need a first
argument to communicate the count of the remaining arguments.
However, because of the way va_start (stdargs.h since the C89/90 standard) is defined, you need
to provide the name of the last required parameter, so that the mechanism knows where to find
the first optional argument. (Some compiler implementations actually ignore this information,
because they can figure it out on their own, but that’s not the case in all environments. For
portability, you need to provide the name of the last required parameter.) So, even if you don’t
really need that first argument because you have a sentinel value at the end of your argument
list, you still need a required “dummy” parameter to provide to va_start. The value you pass in
that first parameter doesn’t matter, but its presence is needed for va_start.
The older K&R mechanism, using varargs.h before C was standardized, did not need a first
required parameter, did not require the function to be prototyped with the ellipsis …, and
va_start did not require the name of the last required parameter. You might see this in some old
code. Some compilers have dropped support for varargs.h, and only support stdargs.h.