I have the following function declarations and the function call that works in C. I want to convert the code to C++, but unable to cast it to the correct types.
// definition of functions
static unsigned long (*putcharfunc)(char c, unsigned long);
int uart0_putchar (int ch)
{
while (!(U0LSR & 0x20));
return (U0THR = ch);
}
// calling from main.cpp
rprintf_devopen(uart0_putchar);
Errors:
../main.cpp:367: error: invalid conversion from 'int (*)(int)' to 'long unsigned int (*)(char, long unsigned int)'
../main.cpp:367: error: initializing argument 1 of 'void rprintf_devopen(long unsigned int (*)(char, long unsigned int))'
uart0_putchar does not take 2 arguments. The function pointer does. I am very surprised that compiles in C, it shouldn't do, not without generating lots of warnings.
Well, C does this correct. Techically you can pass two or more arguments to the function that expects only one argument - this won't break at the binary level. That is why warning is ok here and the code works. However, it would probably fail the other way round - if you passed only one argument to a two argument function. Probably the called function would get some garbage then as a second argument (but still it wouldn't segfault).
C is a weakly-typed language with a philosophy "programmer is always right - if he wants me to do this, I'll do". C++ is also a weakly-typed language, but a bit hardened, so some of the C warnings now became errors. Therefore it is slightly harder to shoot yourself in a foot (but still easy to get the whole leg blown away).
The code has instances where sometimes there are two arguments and in other cases only one. Just so we focus on the type conversion, I changed the function only to a one argument function and redid the problem. The results are exactly the same.
int uart0_putchar (int ch)
{
while (!(U0LSR & 0x20));
return (U0THR = ch);
}
//Compiled as a C file
../main.c:367: warning: passing argument 1 of 'rprintf_devopen' from incompatible pointer type
//Compiled as a C++ file
../main.cpp:367: error: invalid conversion from 'int (*)(char)' to 'long unsigned int (*)(char)'
../main.cpp:367: error: initializing argument 1 of 'void rprintf_devopen(long unsigned int (*)(char))'