Pointers in C are powerful and confusing at the same time. As we can point a pointer to structs, strings or arrays, we can point to function.

Signature: void (*POINTER_NAME) (args)

Say for example we have a function add that adds two number int add(int a, int b)

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

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

The function pointer for this would be

int (*fun_ptr) (int, int)

We can assign this pointer to any function that accepts two int params and return an int.

To point to add function we can just assign it to the fun_ptr pointer as follows.

Now we can use the function pointer as follows

// assign it to add function
fun_ptr = add;
printf("2 + 3 = %d\n", fun_ptr(2, 3));

// assign it to mul function
fun_ptr = mul;
printf("2 * 3 = %d\n", fun_ptr(2, 3));

Now if we want to use function pointer as a function param we can use it directly or use a typedef as follows

// it takes a function pointer as param
int do_op(int a, int b, int (*ptr) (int, int)) {
  return ptr(a, b);
}
printf("2 + 3 = %d \n", do_op(2, 3, add));
printf("2 + 3 = %d \n", do_op(2, 3, mul));

As writing the function signature as a function param is hard, we can use the typedef to give it a new name

// using typedef
typedef int (*op_ptr_type) (int, int);
int do_op2(int a, int b, op_ptr_type ptr) {
  return ptr(a, b);
}
printf("2 + 3 = %d\n", do_op2(2, 3, add));
  printf("2 * 3 = %d\n", do_op2(2, 3, mul));

Here is the complete example in repl.it

Now, lets see how qsort takes advantage of function pointer.

The method signature of qsort is

void qsort(void *ptr, size_t count, size_t size, int (*comp)(const void *, const void *));

Here we can see the fourth param is a callback which is used to do custom comparison. If we want to sort some numbers in ascending order we need to define the comp function first using the same signature

int comp_int_asc(const void* a, const void* b) {
    // dereference to int
    int val1 = *(const int*)a;
    int val2 = *(const int*)b;

    if (val1 < val2) {
        return -1;
    } else if (val1 > val2) {
        return 1;
    }
    return 0;
}

we can use it in the qsort function as follows

int nums[] = {5, 1, 3, 9, 10, 8, -5, 0};
int int_size = sizeof(int);
int arr_len = sizeof(nums) / int_size;
// qsort is defined in stdlib
qsort(nums, arr_len, int_size, comp_int_asc);

Here is the full qsort example