ANSI C: If a function pointer points to executable

2019-05-18 18:56发布

问题:

This question already has an answer here:

  • Does Function pointer make the program slow? 8 answers

We know that using function pointers in C can be quite helpful when used in the proper scenarios (calling a function at runtime vs compile time, making the code more readable, etc.), but there isn't much literature around simple function invocation vs using a function pointer.

void foo(void) {
    printf("hello\n");
}

int testFcn(void) {

    // simple invokation
    foo();

    return 0;
}

// Or, declare function pointer and assign
void (*myFunc)(void) = foo;

int testFcn(myFunc) {

    // Function pointer invokation.
    myFunc();

    return 0;
}

Perhaps the only real way to tell is to analyze the .lst files and .map files?

回答1:

In general case, when function pointer is stored in data segment's memory, invoking a function through such a pointer will involve more overhead, not less overhead.

The real-life performance might vary greatly, depending on whether the pointer is in the CPU cache, already loaded into CPU register, properly predicted by branch prediction mechanism and other factors.



回答2:

A call through a function pointer pretty much necessarily has more, not less overhead than a simple function call. Why? Simply because an indirect function call using a function pointer makes it harder to do optimizations such as function inlining, because the compiler cannot deduce beforehand which function will be called.

Given your example code, a smart compiler can deduce that

void foo(void) {
    printf("hello\n");
}

int testFcn(void) {
    foo(); 
    return 0;
}

foo can be inlined into testFcn - as if it was written

int testFcn(void) {
    printf("hello\n");
    return 0;
}

yet the behaviour would be the same. However, such inlining cannot generally occur if a function pointer is used, because it can be changed before and between the invocations.



回答3:

Real function calls always involve function pointers internally so the ptr-example should be at best equivalent.

Practically, calls via pointers are often worse because they may prevent the compiler from inlining (if the pointer isn't const or the compiler isn't very smart) and they may introduce additional layers of indirection if the pointer is global and not static/DSO-hidden (will have to go through the GOT if you're compiling PIC). If the pointer isn't in cache, fetching it will be expensive too.



回答4:

What is the basis for this question? What makes you think that using a function pointer could have less overhead than invoking the function directly? Why would you expect that doing something indirectly would be faster than doing something directly?

Suppose that using a function pointer were somehow faster than invoking the function directly. If so, then it would be a trivial optimization for compilers to automatically convert all functions to function pointers! With such an optimization, you wouldn't be able to see any difference, so invoking via function pointers could never be observably faster.



回答5:

Function pointer is NO less overhead than normal simply function call.

It allows you to use variable as function pointer, for example as parameter to function for callback, or any other usage.

void do_something(int (*get_value_callback)(void)) {
    int a;

    a = get_value_callback();
    printf("%d\n", a);
}

And then you can use it as this:

int func_ptr_1(void) { return 1; }
int func_ptr_2(void) { return 2; }

do_something(func_ptr_2); //Prints 1
do_something(func_ptr_2); //Prints 2

This is a example, how you can use function pointers acting like prototypes but there is no less overhead than in normal call. You can expect more overhead, not less. Real performance depends on many things and varies between CPUs.