2

I have 2 functions that have same parameters and return type. Like

int fun1(int a){
  return a+1;
}

int fun2(int a){
  return a+2;
}

I made a funtion pointer int(*funptr)(int).

And I want to use malloc and make funptr[0] to point fun1, and funptr[1] to point fun2.

So I tried like

int(*funptr)(int)=(int*)malloc(2*sizeof(funptr));  

but it doesn't work. What can I do?

bruno
  • 32,421
  • 7
  • 25
  • 37
DDDDDDDDD
  • 21
  • 1

4 Answers4

3

What I understand is you need an array of function pointers. Change

 int(*funptr)(int)

to

int  (*funptr)[2] (int)

and use funptr[0] = fun1; and funptr[1] = fun2;

Alternatively, if you must use allocated memory, you can use a pointer to function pointer

int (**funptr)(int);

and then use accordingly. For ease of use, do use typedef.

 typedef int(*funptr)(int);

 funptr * fp;
 fp = malloc(2* sizeof*fp);
 fp[0] = fun1;
 fp[1] = fun2;
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
1

Just do a simple array of function pointers.

int (*f)[2](int); 
f[0] = fun1;
f[1] = fun2;

Use typedefs if you think the declaration syntax is tricky.

Another thing, if you want you can use malloc instead if you want, but Don't cast malloc

Here you actually made a mistake. You should have casted to a function pointer and not an integer pointer. Well, you should not have casted at all. Here it what it should have looked like:

int (**f)(int) = malloc(2 * sizeof *f); 
if(!f) { /* Handle error */ } 
f[0] = fun1;
f[1] = fun2;
free(f);
klutt
  • 30,332
  • 17
  • 55
  • 95
  • @bruno I did address it earlier, but it's more clear now. – klutt Jun 08 '20 at 08:43
  • @bruno Also, since you seem to be on a revenge vote crusade (5 of my answers serially downvoted after our discussion), I hope you realize that this behavior is why most users hesitate to motivate their downvotes and instead just do it silently. – klutt Jun 08 '20 at 11:13
  • @bruno Well, right after our discussion there was a serial downvoting that is now reversed as can be seen here. https://i.stack.imgur.com/Jowr2.png If that's not you and it just happens to be a coincidence, then all is good and I apologize if I accused you of something you did not do, but I'll leave it to the moderators to investigate it. – klutt Jun 08 '20 at 11:54
0

You cant index function pointers. You need to declare the array of function pointers or pointer to pointer to function

int fun1(int a){
    return printf("%s\n",__FUNCTION__);
}
int fun2(int a){
    return printf("%s\n",__FUNCTION__);
}

typedef int func(int);

int main()
{
    func *farr[2];

    farr[0] = fun1;
    farr[1] = fun2;

    for(int x = 0; x < 20; x++)
    {
        farr[(rand() & 1)](1);
    }
}

or everything together

int fun1(int a){
    return printf("%s\n",__FUNCTION__);
}
int fun2(int a){
    return printf("%s\n",__FUNCTION__);
}

int fun3(int a){
    return printf("%s\n",__FUNCTION__);
}

int fun4(int a){
    return printf("%s\n",__FUNCTION__);
}

typedef int func(int);
typedef int (*fa[2])(int);

int main()
{
    func *farr[2];
    func **fapp = malloc(2*sizeof(*fapp));
    fa *fap = malloc(2 * sizeof(*fap));

    farr[0] = fun1;
    farr[1] = fun2;

    fapp[0] = fun1;
    fapp[1] = fun2;

    fap[0][0] = fun1;
    fap[0][1] = fun2;
    fap[1][0] = fun3;
    fap[1][1] = fun4;

    for(int x = 0; x < 20; x++)
    {
        farr[(rand() & 1)](1);
    }

    printf("------------------------------\n");

    for(int x = 0; x < 20; x++)
    {
        int x = rand() % 4;
        fap[x / 2][x & 1](1);
    }

    printf("------------------------------\n");

    for(int x = 0; x < 20; x++)
    {
        fapp[rand() & 1](1);
    }
}

https://godbolt.org/z/OSFGSp

0___________
  • 60,014
  • 4
  • 34
  • 74
0

You almost certainly do not want to allocate an array of functions pointers dynamically. Bad idea.

If you insist, then first of you must realize that malloc always returns an object pointer of type void*, which is incompatible with function pointers. As is your current senseless cast to int*. So you need to go to some well-defined middle ground in between function pointers and object pointers, like a uintptr_t integer.

It is getting tedious to over and over again tell people to use typedef when working with function pointers, so I'm not gonna do that yet again. This will be messy even with such a typedef.

Given typedef int func_t (int);, an array of function pointers is func_t* arr[2];. However, since you use malloc, you actually need to use a pointer to such an array: func_t* (*funptr)[2].

The malloc call will be malloc(sizeof(func_t*[2])). However, as mentioned you need to cast the result into something that isn't an object pointer and pray that it's still portable: (uintptr_t)malloc(sizeof(func_t*[2]));. This is the least questionable I can come up with.

Then you must cast that one to a pointer to array of function pointer type. (func_t*(*)[2]).

The abomination end result:

typedef int func_t (int);

int main (void)
{
  func_t* (*funptr)[2] = (func_t*(*)[2]) (uintptr_t)malloc(sizeof(func_t*[2]));

  (*funptr)[0](1);
  (*funptr)[1](1);

  free(funptr);
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • @bruno Because that level of program behavior change in run-time is unlikely necessary. It's almost certainly an "XY problem"; if you find yourself in need of a variable amount of function calls to a variable behavior functions, there is very likely a problem with the specification and design. As always, when you find yourself in need of obscure program constructs that aren't commonly used by any other programmer. It's very unlikely that you've come across an unique programming problem that calls for complex, obscure solutions and it's very likely that a simpler, correct solution exists. – Lundin Jun 08 '20 at 08:11
  • @bruno The code in the answer speaks for itself: it's a horrible, unreadable mess. Yet this is how you must do it if you want to avoid UB, fragmented allocation etc. – Lundin Jun 08 '20 at 08:29