int valid (int x, int y) {
return x + y;
}
int invalid (int x) {
return x;
}
int func (int *f (int, int), int x, int y) {
//f is a pointer to a function taking 2 ints and returning an int
return f(x, y);
}
int main () {
int val = func(valid, 1, 2),
inval = func(invalid, 1, 2); // <- 'invalid' does not match the contract
printf("Valid: %d\n", val);
printf("Invalid: %d\n", inval);
/* Output:
* Valid: 3
* Invalid: 1
*/
}
At the line inval = func(invalid, 1, 2);
, why am I not getting a compiler error? If func
expects a pointer to a function taking 2 ints and I pass a pointer to a function that takes a single int, why isn't the compiler complaining?
Also, since this is happening, what happens to the second parameter y
in the invalid
function?
If you declare a formal parameter of a function as a pointer type, you are passing that parameter by its address. The pointer is copied, but not the data it points to. So, Pass By Address offers another method of allowing us to change the original argument of a function (like with Pass By Reference).
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.
A pointer is a variable that holds a memory address. A reference has the same memory address as the item it references. A pointer needs to be dereferenced with * to access the memory location it points to, whereas a reference can be used directly.
why isn't the compiler complaining?
Maybe you need a better compiler? gcc says warning: passing argument 1 of ‘func’ from incompatible pointer type
on this code.
Also, since this is happening, what happens to the second parameter y in the invalid function?
Probably what happens is that the compiler does whatever it would normally do to pass a parameter (push it on the stack, put it in a designated register, etc). Calling a function with the wrong number of parameters is undefined behavior, though, so there are no guarantees - the program could crash, or the compiler could make monkeys fly out of your nose.
Assuming you're ignoring all the compiler warnings that this should give you, you can think about what happens like this:
Your code is attempting to call a function which takes two ints, and returns one. Depending on the calling convention the parameters might be passed in registers on the cpu or on the stack, the output probably goes to a register. The valid
call works fine, everything is where it's expected. For the invalid
call the same stack is set up, with the two parameters as that's what the program thinks it's calling, then the function is called.
Apparently with your platform it so happens that the solitary argument for invalid
is in the same location as the first parameter for valid
, so that invalid
coincidentally does what you would have expected calling it properly. How the parameters are cleaned up is unspecified - if the called function is supposed to clean up the space for its parameters your stack will be fried, if the calling function cleans up then your program will possibly continue to function.
Irregardless you are invoking undefined behaviour here. Try changing func
to the single parameter form
int func(int(*f)(int),x){return f(x);}
and see if both calls still work.
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