5
#include <stdio.h>
#include <stdlib.h>

int (*fptr1)(int);

int square(int num){
  return num*num;
}

void main(){
  fptr1 = &square;
  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.

  1. When we call a function by pointer, does pointer have this function's location at code space?
  2. When called function is running is it same as normally called function in main()?
  3. What is the difference of calling function directly or using function pointer when code is running in a pipelined branch predictive processor?
Mat
  • 202,337
  • 40
  • 393
  • 406
cycrel
  • 97
  • 2
  • 10

4 Answers4

10

The best way to answer this is to look at the disassembly (slightly modified sample):

fptr1 = &square;
int result1 = fptr1(5);
int result2 = square(5);

Results in this x64 asm:

    fptr1 = &square;
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).

  1. Yes, you can see in the assignment of the function pointer, that it stores the code address of the 'square' function.
  2. From a stack setup/tear down: Yes. From a performance perspective, there is a slight difference as noted above.
  3. There are no branches, so there is no difference here.

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.

josh poley
  • 7,236
  • 1
  • 25
  • 25
5
  1. The pointer to function contains the address of the start of the function in the text segment of the program.
  2. Once called, the function runs identically whether it is called directly or by a pointer to function.
  3. I'm not sure. Often, there won't be much difference; the pointer to function doesn't change very often, if at all (e.g. because you loaded a shared library dynamically, so you have to use a pointer to function to call the function).

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • By "start of the function", did you mean the 0'th index of the, let's say, the "bytecode array" of the function call/frame? – stdout Mar 26 '17 at 15:12
  • Byte code isn't normally a term used with C. The start of the function is the address to which the program jumps when the function is called. It is normally prologue code that adjusts where variables are stored, etc, which is roughly what the call frame is. – Jonathan Leffler Mar 26 '17 at 17:17
  • For sure, there's no such thing in C. I just wanted to visualise/materialise "the address" thing that gets pointed by a function pointer. I think in any case, the flow has to do some initialisation for the incoming function frame/call (and probably set PC to the value of the underlying function pointer) before going any further. – stdout Mar 26 '17 at 20:25
3
  1. Yes
  2. Absolutely
  3. No difference

Calling a function through a function pointer is just a convenience; and makes it possible to pass a function as a parameter to another function. See for example, qsort()

amrith
  • 953
  • 6
  • 17
  • I would not be absolutely sure about 3. If the value of the pointer changes often in a (for the processor) unpredictable way, then the branch prediction may be wrong in more cases. – FrankPl Aug 16 '13 at 23:49
2

There's no difference between calling a function by its name and calling it through a function pointer. The purpose of function pointers is so that you can call a function that's specified somewhere else. For instance, the qsort() function takes a function pointer as an argument that it calls to determine how to order the elements of the array, rather than having only one comparison method.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • This is good example there are few more benefits I learn from [Regarding function pointers in embedded systems](http://stackoverflow.com/questions/4836245/function-pointers-in-embedded-systems-are-they-useful) – Grijesh Chauhan Aug 17 '13 at 04:44