Post

Function Pointers

Function Pointers

Function Pointers


Prerequisites


1. What is a Function Pointer?

A function pointer is a variable that stores the address of a function. Just like pointers to variables, but pointing to functions

1
return_type (*pointer_name)(parameter_types);

Use when:

  • You need C-style callbacks
  • You want low-overhead dynamic dispatch
  • You are working with legacy or embedded systems
✔️ Example
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

int add(int a, int b)
{
    return a + b;
}

int main()
{
    int (*funcPtr)(int, int) = add;

    std::cout << funcPtr(2, 3);  // 5
}

funcPtr now points to add

2. Why Use Function Pointers?

2-1. Callback Functions

1
2
3
4
void execute(int (*func)(int, int))
{
    std::cout << func(2, 3);
}

2-2. Dynamic Behavior

1
2
3
4
5
6
7
8
9
10
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }

int (*op)(int, int);

op = add;
std::cout << op(5, 3);  // 8

op = sub;
std::cout << op(5, 3);  // 2

2-3. Table of Functions

1
2
3
4
5
6
7
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }

int (*ops[2])(int, int) = {add, sub};

std::cout << ops[0](3, 2);  // add
std::cout << ops[1](3, 2);  // sub

3. Performance Characteristics

✔️ Direct Call
1
add(2, 3);
✔️ Function Pointer Call
1
funcPtr(2, 3);
AspectDirect CallFunction Pointer
Inline Optimization✅ Possible❌ Not possible
Branch PredictionBetterSlightly worse
OverheadMinimalSmall overhead
FlexibilityLowHigh

3-1. No Inlining

1
int add(int a, int b) { return a + b; }

Compiler may inline:

1
int result = 2 + 3;  // optimized

But with function pointer:

1
funcPtr(2, 3);

Compiler cannot inline (target unknown at compile time)

3-2. Indirect Call

Function pointer introduces an indirect jump

1
2
Direct call: call add
Pointer call: call [address]

This affects CPU pipeline & branch prediction

  • Usually very small overhead
  • Becomes noticeable in:
    • tight loops
    • high-frequency calls
    • performance-critical systems

4. Function Pointer vs Modern Alternatives

✔️ Function Pointer
1
int (*func)(int, int);
✔️ std::function
1
2
3
#include <functional>

std::function<int(int, int)> func = add;

More flexible but slower

✔️ Lambda

1
auto func = [](int a, int b) { return a + b; };

Often inlined → fastest

MethodSpeedFlexibility
Direct Call🔥 Fastest
Lambda🔥 Fast
Function Pointer⚡ Medium
std::function🐢 Slowest🔥 Most flexible

5. Common Mistakes

❌ Forgetting pointer syntax

1
int *func(int, int);  // ❌ wrong

✔️ Correct:

1
int (*func)(int, int);

❌ Null pointer call

1
2
3
int (*func)(int, int) = nullptr;

func(2, 3);  // ❌ crash

✔️ Always check:

1
2
3
4
if (func)
{
    func(2, 3);
}

6. Function Pointer Typedef

1
2
3
typedef int (*FuncPtr)(int, int);

FuncPtr f = add;

Or (modern C++):

1
2
3
using FuncPtr = int (*)(int, int);

FuncPtr f = add;

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

using Operation = int (*)(int, int);

int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }

int compute(Operation op, int a, int b)
{
    return op(a, b);
}

int main()
{
    std::cout << compute(add, 2, 3);  // 5
    std::cout << compute(mul, 2, 3);  // 6
}
This post is licensed under CC BY 4.0 by the author.