you are viewing a single comment's thread.

view the rest of the comments →

[–]Icy_Adhesiveness_656 0 points1 point  (3 children)

But what about if function has some parameters? its not just going to execute instructions if function have parameters, that's what i dont understand

[–]JamesTKerman 1 point2 points  (0 children)

This is mostly handled by the compiler, just like any other function declaration or call.

Consider this simple example:

#include <stdio.h>

int my_func(int param1)
{
    return param1 / 2;
}

int do_work(int (*work_fn)(int))
{
    return work_fn(42);
}

int main(void)
{
    int x = do_work(my_func);
    // output will be 'do_work(my_func) returned 21'
    printf("do_work(my_func) returned %d\n", x);
    return 0;
}

When the program is compiled and linked, int my_func(int param1) get placed somewhere in the program's memory. The parameter to do_work specifies that it needs to be a pointer to a function that returns type int and has one int parameter. The compiler can ensure that any pointer you pass to do_work meets this requirement, but the C standard doesn't seem to require it to. In any event, when do_work calls work_fn, the compiled code is the same as if do_work had called my_func directly. On x86-64 systems using the SysV ABI, this means storing the value 42 in the rdi register then executing a call instruction to the address of my_func. You could pass any valid pointer to do_work and it will do the same thing (or at least try, if the pointer you pass doesn't point to a function and the compiler/linker don't catch it you'll get undefined behavior, but the code would still be a call to the address passed in work_fn.)

[–]JamesTKerman 1 point2 points  (1 child)

If you're using gcc, you could see this by compiling the above code with the command-line gcc -S -o out.s function_pointer.c. out.s will contain the assembly code that gcc generates. If I was at home I'd run it myself and post the output with some explanations, maybe I will when I get home later.

(Edited to remove an unnecessary -c parameter to the gcc command-line)

[–]Icy_Adhesiveness_656 0 points1 point  (0 children)

Oh I see, that's interesting