Why C variadic functions need a required first parameter

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.

Leave a Reply