Why is void f (...) not allowed in C?

Why does C not allow a function with a variable-length argument list, for example:

void f(...) { // do something... } 
+6
source share
6 answers

I think the motivation for claiming that varargs functions must have a named parameter is the uniformity of va_start . For ease of implementation, va_start takes the name of the last named parameter. With a typical convention of calling varargs and depending on the direction arguments, va_arg will find the first vararg at (¶meter_name) + 1 or (first_vararg_type*)(¶meter_name) - 1 , plus or minus some addition to ensure alignment.

I don’t think there is any special reason why the language cannot support varargs functions without named parameters. For use in such functions, there must be an alternative form of va_start , which would have to get the first vararg directly from the stack pointer (or be a pedantic frame pointer, which is actually the value that the stack pointer was included in the function, since the code in the function could move sp from the moment the function is entered). This is possible in principle - any implementation must have access to the [*] stack in some way, at some level - but this may annoy some developers. Once you know the varargs calling convention, you can usually implement va_ macros without any other implementation-specific knowledge, and this also requires knowing how to access the call arguments directly. I implemented these varargs macros before, in the emulation layer, and that would annoy me.

In addition, there is not much practical use for a varargs function without named parameters. There is no language function for the varargs function to determine the type and number of variable arguments, so the caller must know the type of the first vararg in any case in order to read it. Thus, you can also make it a named parameter with a type. In printf and friends, the value of the first parameter tells the function what types belong to varargs, and how many of them are.

I believe that in theory the caller could look at some global question, how to understand the first argument (and whether there is one), but this is rather unpleasant. Of course, I would not be going to come to terms with this, and adding a new version of va_start with an additional burden for downloading will be on my part.

[*], or if the implementation does not use the stack, regardless of what it uses instead, to pass arguments to the function.

+10
source

In a variable-length argument list, you must declare the type of the first argument - this is the language syntax.

 void f(int k, ...) { /* do something */ } 

will work fine. Then you need to use va_list , va_start , va_end , etc. Inside a function to access individual arguments.

+9
source

C allows variable length arguments, but for this you need to use va_list, va_start, va_end, etc. . Do you think printf and friends are implemented? However, I would recommend against this. You can usually do a similar thing more cleanly using an array or structure for parameters.

+1
source

Playing with this, I made this pleasant implementation, which, it seems to me, some people will want to consider.

 template<typename T> void print(T first, ...) { va_list vl; va_start(vl, first); T temp = first; do { cout << temp << endl; } while (temp = va_arg(vl, T)); va_end(vl); } 

It ensures that you have one variable minimum, but allows you to put them all in a loop in its purest form.

+1
source

There is no intrigue why C cannot accept void f (...). It might, but the "designers" of this C function decided not to.

My assumptions about their motives are that in order for void f (...) to require more "hidden" code (which can be considered as runtime) than not to allow it: to make a distinguishable case of f () from f (arg) (and others), C should provide a way to count the number of arguments, and this requires more generated code (and probably a new keyword or special variable, like "nargs" to get a counter) and C usually trying to be as minimal as possible.

0
source

... does not allow any arguments, i.e. for int printf(const char *format, ...); the operator

 printf("foobar\n"); 

.

If you do not specify at least one parameter (which should be used to check additional parameters), there is no way for the function to “know” how it was called.

All of these statements will be valid.

 f(); f(1, 2, 3, 4, 5); f("foobar\n"); f(qsort); 
-2
source

Source: https://habr.com/ru/post/891951/


All Articles