I'm just beginning to wrap my head around function pointers in C. To understand how casting of function pointers works, I wrote the following program. It basically creates a function pointer to a function that takes one parameter, casts it to a function pointer with three parameters, and calls the function, supplying three parameters. I was curious what would happen:
#include <stdio.h>
int square(int val){
return val*val;
}
void printit(void* ptr){
int (*fptr)(int,int,int) = (int (*)(int,int,int)) (ptr);
printf("Call function with parameters 2,4,8.\n");
printf("Result: %d\n", fptr(2,4,8));
}
int main(void)
{
printit(square);
return 0;
}
This compiles and runs without errors or warnings (gcc -Wall on Linux / x86). The output on my system is:
Call function with parameters 2,4,8.
Result: 4
So apparently the superfluous arguments are simply silently discarded.
Now I'd like to understand what is really happening here.
I'm coming from Java, where typechecking is a lot stricter, so this behaviour confused me a bit. Maybe I'm experiencing a cultural shock :-).
Yes, it can. This is purpose of casting function pointers, just like usual pointers. We can cast a function pointer to another function pointer type but cannot call a function using casted pointer if the function pointer is not compatible with the function to be called.
The only things you can do with a function pointer are read its value, assign its value, or call the function that it points toward. You cannot increment or decrement the address stored in a function pointer or perform any other arithmetic operations.
Pass-by-pointer means to pass a pointer argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the variable to which the pointer argument points. When you use pass-by-pointer, a copy of the pointer is passed to the function.
There are three ways to pass variables to a function – pass by value, pass by pointer and pass by reference.
If you take a car and cast it as a hammer the compiler will take you at your word that the car is a hammer but this does not turn the car into a hammer. The compiler may be successful in using the car to drive a nail but that is implementation dependent good fortune. It is still an unwise thing to do.
The extra parameters are not discarded. They are properly placed on the stack, as if the call is made to a function that expects three parameters. However, since your function cares about one parameter only, it looks only at the top of the stack and does not touch the other parameters.
The fact that this call worked is pure luck, based on the two facts:
There is no way the compiler can warn you about potential problems like this for one simple reason - in the general case, it does not know the value of the pointer at compile time, so it can't evaluate what it points to. Imagine that the function pointer points to a method in a class virtual table that is created at runtime? So, it you tell the compiler it is a pointer to a function with three parameters, the compiler will believe you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With