I know that declaring a function (or function pointer) with no parameter list (and without specifying void
in the parameter list) that means that the function (or function pointer) has an unknown number of arguments.
I wrote some test scripts to check this behavior out:
int my_func_1() {
return(0);
}
int my_func_2(int x) {
return(x);
}
int my_func_3(char x, ...) {
va_list va;
va_start(va, x);
return(va_arg(va, int));
}
int (*fp)();
fp = my_func_1;
printf("%d\n", fp());
fp = my_func_2;
printf("%d\n", fp(33));
fp = my_func_3;
printf("%d\n", fp(33, 44));
Which I've compiled on a 64 bit machine under linux as such:
gcc test.c -Wextra -pedantic -std=c1x -O3 -o test
The output is correct:
0
33
44
But I get this warning: assignment from incompatible pointer type
. How come this warning only shows up when using the vararg ellipsis?
Since the pointer type is considered incomplete assigning it a complete type should not constitute an "assignment from incompatible pointer type". Moreover, assigning complete types works without any warnings as long as the vararg ellipsis is not present
This other question asks nearly the same thing. The answers are all in the line of "it doesn't work that way" with no clear reference to the standard as to why it wouldn't work that way.
- Why does the compiler generate the warning?
- Is this behavior (warning aside) reliable?
- Is this behavior compiler specific (reading the other question it appears that mingw x86_64 didn't support it in 2011)?
- Is this behavior platform specific?
See 6.7.5.3 of the C Standard:
This says that the assignment of the varargs function to fp has incompatible types.
In addition, as I noted in my comments above, the program has undefined behavior which by definition is unreliable ... it may work in one version of one implementation on one platform but fail in other versions, implementations, and platforms ... it might even work one day but not the next, or in one part of a program but not another. Pragmatically, in some implementations the calling sequences of varargs and non-varargs functions are different, and your program is likely to crash when run on such an implementation.