#include <stdio.h>
#include <stdlib.h>
int (*fptr1)(int);
int square(int num){
return num*num;
}
void main(){
fptr1 = □
printf("%d\n",fptr1(5));
}
Can someone briefly explain what happens in stack when we call a function pointer? What is the difference between calling a function directly in main() and calling it by function pointer in C language by the means of physical memory and process?
I tried to understand what happens in memory when we call a function with function pointer but it is not enough to me.
The best way to answer this is to look at the disassembly (slightly modified sample):
fptr1 = □
int result1 = fptr1(5);
int result2 = square(5);
Results in this x64 asm:
fptr1 = □
000000013FA31A61 lea rax,[square (013FA31037h)]
000000013FA31A68 mov qword ptr [fptr1 (013FA40290h)],rax
int result1 = fptr1(5);
000000013FA31A6F mov ecx,5
000000013FA31A74 call qword ptr [fptr1 (013FA40290h)]
000000013FA31A7A mov dword ptr [result1],eax
int result2 = square(5);
000000013FA31A7E mov ecx,5
000000013FA31A83 call square (013FA31037h)
000000013FA31A88 mov dword ptr [result2],eax
As you can see the assembly is virtually identical between calling the function directly and via a pointer. In both cases the CPU needs to have access to the location where the code is located and call it. The direct call has the benefit of not having to dereference the pointer (as the offset will be baked into the assembly).
Edit: If we were to interject branches into the above sample, it wouldn't take very long to exhaust the interesting scenarios, so I will address them here:
In the case where we have a branch before loading (or assignment) of the function pointer, for example (in pseudo assembly):
branch zero foobar
lea square
call ptr
Then we could have a difference. Assume that the pipeline chose to load and start processing the instructions at foobar
, then when it realized that we weren't actually going to take that branch, it would have to stall in order to load the function pointer, and dereference it. If we were just calling a know address, then there would not be a stall.
Case two:
lea square
branch zero foobar
call ptr
In this case there wouldn't be any difference between direct calls vs through a function pointer, as everything we need is already know if the processor starts executing down the wrong path and then resets to start executing the call.
The third scenario is when the branch follows the call, and that is obviously not very interesting from a pipeline perspective as we've already executed the subroutine.
So to fully re-answer question 3, I would say Yes, there is a difference. But then the real question is whether or not the compiler/optimizer is smart enough to move the branch after the function pointer assignment, so it falls into case 2 and not case 1.
What is the difference between calling a function directly in main() and calling it by function pointer?
The only difference is possibly an extra memory reference to fetch the function pointer from memory.
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