I'm trying to reconcile 2 things.
I know that a function signature TYPE func(void); means the function accepts no arguments, which is different than: TYPE func();, which means the function accepts any arguments (and this is difference in C vs. C++).
I also know that function pointers are not compatible with functions that have different arguments (different signatures) (sorry if I'm phrasing this wrong).
I have read that you can cast a function pointer to a different type, and then back again, and then you can call the function (i.e. it works "round trip").
However, I am interested in what happens when calling functions that accept different arguments through a pointer. I know this probably falls under undefined behavior. But what I find strange is the notion that the function accepts "any arguments". Maybe this interpretation is wrong.
But I'll explain now with an example.
#include <stdio.h>
#include <stdbool.h>
void (*func)(); /* accepts any arguments */
void func_1(int x); /* 1 argument */
void func_2(int x, float y); /* 2 arguments */
enum MODE {PRINT_THEM, NOTE_THEM} mode;
int main(void)
{
printf("Printing...\n");
mode = PRINT_THEM;
func_1(8);
func_2(9, 10.0F);
printf("Noting...\n");
mode = NOTE_THEM;
func = func_1;
func(); /* function can have any arguments, so this one has 1, but it's not used */
func = func_2;
func(); /* function can have any arguments, so this one has 2, but they are not used */
return 0;
}
void func_1(int x)
{
if (mode == NOTE_THEM)
printf("func_1() has 1 argument: (int)\n");
else /* mode == PRINT_THEM */
printf("x == %d\n", x);
}
void func_2(int x, float y)
{
if (mode == NOTE_THEM)
printf("func_2() has 2 arguments: (int, float)\n");
else /* mode == PRINT_THEM */
printf("x == %d, y == %f\n", x, y);
}
The overall idea here is when mode == PRINT_THEM, you use the arguments, and therefore the arguments matter, and you can't use the function pointer.
However when mode == NOTE_THEM, you don't use the arguments, and therefore their particular values don't matter (they could be anything, even a garbage value would be fine). In this case, since the arguments don't matter, ideally the function pointer that accepts any arguments (in this case no arguments) could be used.
The thing I want to avoid is being forced to use some kind of placeholder arguments, when they don't matter. For example:
mode = NOTE_THEM;
func_1(placeholder_int);
func_2(placeholder_int, placeholder_float);
The only solution I can think of actually does not involve function pointers at all, but you could use C99 compound literals, and rely on default initialization, in order to call the function with the right arguments (satisfy the compiler), but not care about their specific values or what they specifically are. Kind of like this:
mode = PRINT_THEM;
func_1( (FUNC_1_ARGS){8} );
func_2( (FUNC_2_ARGS){9, 10.0F} );
mode = NOTE_THEM;
func_1( (FUNC_1_ARGS){} );
func_2( (FUNC_2_ARGS){} );
TYPE func();, which means the function accepts any arguments" isn't quite right. In previous editions of C,func();declared a function that takes a not-yet-specified number of arguments. However, the corresponding function definition would need to specify a fixed number of arguments. This was mostly for compatibility with old-style K&R function definitions. Attempting to call a function with just afunc();declaration is UB. This was also done away with entirely in C23. Nowadays,func();is exactly equivalent tofunc(void);(...)is invalid. There needs to be at least one non-variadic parameter before the, ....