Function pointers are easy!

Function pointers in C are pointers that point to functions. In other words, while a regular pointer holds the address of a variable, a function pointer holds the address of a function. Function pointers are used for dynamic function calls - the function to be called can be decided at runtime.

Syntax

The syntax for declaring a function pointer is similar to a function declaration, with the name of the pointer wrapped in parentheses and preceded by an asterisk. For example, if you have a function int func(int, int), a pointer to this function is declared as int (*func_ptr)(int, int).

Sample Code

Here's a basic example:

#include <stdio.h>

// A simple function that adds two integers
int add(int a, int b) {
    return a + b;
}

// A simple function that subtracts two integers
int subtract(int a, int b) {
    return a - b;
}

// A function that takes a function pointer as an argument
void print_operation(int (*operation)(int, int), int a, int b) {
    printf("Result: %d\n", operation(a, b));
}

int main() {
    // Declaring function pointers for add and subtract
    int (*func_ptr)(int, int);

    int choice, a, b;

    printf("Enter two numbers: ");
    scanf("%d %d", &a, &b);

    printf("Choose the operation:\n");
    printf("1. Add\n");
    printf("2. Subtract\n");
    scanf("%d", &choice);

    // Assigning the appropriate function to the function pointer
    if (choice == 1) {
        func_ptr = add;
    } else if (choice == 2) {
        func_ptr = subtract;
    } else {
        printf("Invalid choice\n");
        return 1;
    }

    // Passing the function pointer to another function
    print_operation(func_ptr, a, b);

    return 0;
}

The provided C program demonstrates the use of function pointers to dynamically select and execute a function based on user input. The program has two basic arithmetic functions (add and subtract) and allows the user to choose which operation to perform at runtime. Let's break down and explain each part of the program:

Function Definitions

  • add Function: This function takes two integers (a and b) as arguments and returns their sum (a + b).

  • subtract Function: Similar to add, this function takes two integers and returns their difference (a - b).

The print_operation Function

  • Purpose: This function demonstrates the power of function pointers. It takes a function pointer (operation) as an argument along with two integers (a and b).

  • Function Pointer Argument: The function pointer operation is expected to point to a function that takes two integers and returns an integer.

  • Execution: Inside print_operation, the function pointed to by operation is called with a and b as arguments, and the result is printed.

The main Function

  • Variable Declarations:

    • func_ptr: A function pointer that can point to functions like add and subtract.

    • choice, a, b: Variables to store user input.

  • User Input: The program asks the user to input two numbers and then choose an operation (1 for addition, 2 for subtraction).

  • Assigning the Function Pointer:

    • Based on the user's choice, func_ptr is assigned to point to either the add or subtract function.

    • This assignment is crucial as it determines which function will be called later. The decision of which function func_ptr points to is made at runtime, not at compile time.

  • Dynamic Function Call:

    • The program then calls print_operation, passing it the function pointer func_ptr and the user-provided numbers a and b.

    • Since func_ptr can point to either add or subtract (based on the user's choice), the actual function call is dynamically determined at runtime.

    • This demonstrates a key aspect of function pointers: the ability to defer the decision of which function to execute until runtime.

Runtime vs Compile Time

  • Compile Time: When the program is compiled, it's not determined which function (add or subtract) will be executed. The program is compiled knowing only that func_ptr will point to some function that matches the signature int func(int, int).

  • Runtime: It's only during the program's execution, after the user makes a choice, that func_ptr is assigned to a specific function (add or subtract). Thus, the actual function call is resolved at runtime based on user input.

Use Cases

Function pointers are particularly useful in scenarios where behavior needs to be decided at runtime. They are commonly used in:

  1. Callback Functions: Passing a function to another function to be called later.

  2. Implementing Functionality Similar to Polymorphism: In scenarios where different functionalities need to be executed based on the context.

  3. Table of Function Pointers: Often used in implementing state machines or lookup tables.

Example: Callback Functions
#include <stdio.h>

void greet(void (*callback)(const char*)) {
    callback("Hello World!");
}

void englishGreeting(const char* message) {
    printf("English: %s\n", message);
}

void spanishGreeting(const char* message) {
    printf("Spanish: Hola Mundo!\n");
}

int main() {
    greet(englishGreeting);
    greet(spanishGreeting);
    return 0;
}

In this example:

  • greet is a function that takes a function pointer as a parameter. It calls this function, passing "Hello World!" as an argument.

  • englishGreeting and spanishGreeting are callback functions.

  • In main, greet is called with different callback functions, demonstrating how behavior can be changed dynamically.

Function pointers add a lot of flexibility to C programs, enabling more dynamic and adaptable code structures.