2

I need to call a function using an integer. I'm really new to C language and the function pointer is horribly confusing.

Goal

  1. I have so many messy functions which will mess up all if I write them in the main.c.
  2. So I write those messy functions into another c file messy_functs.c
  3. In main.c, I need to select one of those messy functions and call it, depending on the integer obtained from my algorithm. Those functions commonly needs two arguments, int input and int *output.
  4. The callee function will store the result in output which is passed as a pointer

My plan

  1. In messy_functs.c, make an array function_list[] containing function pointers in the global scope.
  2. In messy_functs.c. Make a function get_function_by_index(int function_index) that returns a function pointer indexed by the argument.
  3. In main.c, call messy_function passing function_index and then get the result by calling the returned function passing two arguments int input and int *output.

Problem

I made my code as follows. But failed with an error error: too many arguments to function.. Please ignore some typos.

// main.c
#include "messy_functs.h"
...

void get_result(int func_idx, int input, int *output)
{
    (*get_function_by_index(func_idx))(input, output);
}

int main() {
    int result, data, func_idx;

    ...

    func_idx, data = some_algorithm_i_made(~~);
    get_result(func_idx, data, &result);
    printf("Got the result %d\n", result);

}

============
// messy_functs.c
#define FUNCTION_NUM 100
const void (*function_list[FUNCITON_NUM])(int input, int *output) = {func1, func2, func3, func_m, func_qwer, func_abab, ...(many functions) };

void (*get_function_by_index(int func_id)){
    return function_list[func_id];
}

void func1(int input, int *output) {...}
void func2(int input, int *output) {...}
(... other functions)

I've been tried to fix but got different errors such as void value not ignored as it ought to be. I know there must be other good posts that can solve my problem. I've been read many posts about function pointers and array of function pointers but couldn't make it.

6
  • 2
    Personally, I would shy away from using function pointers, and just have a series of if statements, calling the correct function appropriately. It's easier to understand and read. The times where it makes sense to use function pointers are few, in my experience, especially if you're, "really new to C language" Commented Apr 6, 2021 at 14:23
  • 1
    If you're really married to the idea of a function pointer table, callback and direct function pointers are one of only two places where pointer type aliases (i.e. hiding a pointer type in a typedef alias) are actually helpful. You might want to consider that. You don't have to do so, but as your discovering, the code can get pretty cryptic pretty fast. Commented Apr 6, 2021 at 14:25
  • @MANA624 Thanks for the kind comment. I've been working with Python and it's common to call a function by name or by indexing the function name in an list. So I have some desire to make my code this way. But if if statement is better in C, I would consider it. I would break my finger if I have to type them all. I think I have generate the code using Python. Commented Apr 6, 2021 at 14:30
  • Don't you have to specify the function pointer parameters in void (*get_function_by_index(int func_id))? So something like void (*get_function(int func_id))(int, int *)? Commented Apr 6, 2021 at 14:36
  • @WhozCraig Thanks for your kind comment. Is it something like presented in Wikipedia? Commented Apr 6, 2021 at 14:39

1 Answer 1

3

The proper definition for the array would be:

void (* const function_list[FUNCITON_NUM])(int input, int *output) = ...

And for get_function_by_index would be:

void (*get_function_by_index(int func_id))(int, int*)

When passing or returning function pointers, it's very helpful to have a typedef for the function pointer type to make it easier to manage.

The typedef can be created in messy_functs.h for the function pointer type:

typedef void (*messy_func)(int, int *);

Then in messy_funct.c, use this type for the array:

const messy_func function_list[FUNCITON_NUM] = {func1, func2, func3, func_m, ... };

And for the return type of get_function_by_index

messy_func get_function_by_index(int func_id) {
    return function_list[func_id];
}

And you would call this function like this:

void get_result(int func_idx, int input, int *output)
{
    get_function_by_index(func_idx)(input, output);
}
Sign up to request clarification or add additional context in comments.

3 Comments

As you answered, I used typedef and fixed the function list (maybe qual '=' is missed, right?), and called the function in get_result function. Finally, it builds! And the code looks pretty clearer. Thank you so much!
@hskim In nearly all circumstances hiding pointer types in typedef aliases is counter-productive, generally making the code harder to read, harder to maintain, and to no ultimate benefit. There are only two legitimate cases where they actually bring benefit, and your situation, function pointer management, is one of them (the other being blackbox handle-APIs). As you can see from this answer, using aliases here brings tremendous clarity to the code.
@hskim Yes, there was an = missing. That's been fixed. And glad I could help. Feel free to accept this answer if you found it useful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.