Is there a proper way to access these arguments?
Yes. Specify a parameter list in the function definition with types and identifiers of the function.
You can do it "old style" (don't do it, it should not be used in new code):
int func(a, b, c, d)
int a;
int b;
int c;
int d;
{
printf("%d %d %d %d\n", a, b, c, d);
}
Or normal:
int func(int a, int b, int c, int d) {
printf("%d %d %d %d\n", a, b, c, d);
}
or using stdarg.h :
int func(int a, ...) {
va_list ap;
va_start(va, a);
int b = va_arg(va, int);
int c = va_arg(va, int);
int d = va_arg(va, int);
printf("%d %d %d %d\n", a, b, c, d);
va_end(ap);
}
or using stdarg.h from the second arg:
int func(int a, int b, ...) {
va_list ap;
va_start(va, b);
int c = va_arg(va, int);
int d = va_arg(va, int);
printf("%d %d %d %d\n", a, b, c, d);
va_end(ap);
}
or using stdarg.h from the third arg:
int func(int a, int b, int c, ...) {
va_list ap;
va_start(va, c);
int d = va_arg(va, int);
printf("%d %d %d %d\n", a, b, c, d);
va_end(ap);
}
stdarg.h
needs at least one, first argument in the parameter list to be declared. So there is no way to handle function with unspecified number and type of arguments, but there is a way (stdarg.h
) to handle function with at least 1 argument followed by unspecified number and type of arguments.
... functions of the form void func()
take infinitely many arguments
This is not true. I don't think there is a C standard way to pass infinite number of arguments to a function.
Function of the form func()
take unspecified number and type of arguments. They take a finite number of arguments, but the number is unspecified in the transaction unit where such function declaration is encountered. If the function definition takes 5 arguments, they take 5 arguments, otherwise undefined behavior. The number of arguments is not specified, if the function definition takes elipsis (, ...) in which case no information about the number or types of the parameters after the comma is supplied.
(C11 6.7.6.3p9).
Or do you have to actually mess around with the stack pointer and inline assembly?
Yes, you have to "mess around" with implementation defined behavior.
From GCC docs 18.10:
... The ISO implementation of va_start takes an additional second argument. The user is supposed to write the last named argument of the function here.
However, va_start should not use this argument.
You need to specify the second argument to va_start
. Maybe more on such topic can be found in this thread.
printf("%d %d %d %d\n");
This is undefined behavior. Once your program has undefined behavior, nasal demons start spawning in your room and are fighting for independence. It may have well defined behavior on your platform or implementation, but this is wrong, it's no longer a C language. If there is a "correct" behavior according to your mental model of the language, that model is simply wrong;
from this thread. From the language point of view, nasal demons fight for independence and the program is invalid.