How can I use an array of function pointers?
Asked Answered
C

13

215

How should I use array of function pointers in C?

How can I initialize them?

Chelton answered 31/10, 2008 at 6:45 Comment(0)
A
277

You have a good example here (Array of Function pointers), with the syntax detailed.

int sum(int a, int b);
int subtract(int a, int b);
int mul(int a, int b);
int div(int a, int b);

int (*p[4]) (int x, int y);

int main(void)
{
  int result;
  int i, j, op;

  p[0] = sum; /* address of sum() */
  p[1] = subtract; /* address of subtract() */
  p[2] = mul; /* address of mul() */
  p[3] = div; /* address of div() */
[...]

To call one of those function pointers:

result = (*p[op]) (i, j); // op being the index of one of the four functions

You can also initialize p as:

int (*p[4]) (int, int) = {sum, subtract, mul, div};

As in:

#include <stdio.h>

// Function declarations
int sum(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }
int div(int a, int b) { return (b != 0) ? a / b : 0; }

int main() {
    // Array of function pointers initialization
    int (*p[4]) (int, int) = {sum, subtract, mul, div};

    // Using the function pointers
    int result;
    int i = 20, j = 5, op;

    for (op = 0; op < 4; op++) {
        result = p[op](i, j);
        printf("Result: %d\n", result);
    }

    return 0;
}

As note by Gauthier in the comments

You can call functions by a pointer without dereferencing it.

Some might argue that they want the dereference to be explicit, so they know what they're dealing with.
Others would reply that it's a known idiom, and that there isn't much more that p[op]() could ever mean.

result = p[op](i, j); works

Daniel Heimgartner confirms in the comments:

Initializing the array of pointers p[0] = sum and p[0] = &sum are equivalent.
Similarly, when calling a function (via a function pointer) you do not need to dereference (*) it: See this Stack Overflow question "How come a pointer to a function be called without dereferencing?"

Anyplace answered 31/10, 2008 at 6:48 Comment(8)
@crucifiedsoul "the C Programming Language" written by Brian Kernighan and Dennis Ritchie? It could be, but I didn't have it as a reference at the time I wrote the answer three and an half year ago. So I don't know.Anyplace
I'd like to add you can initialize p with (*p[4]) (int, int) {sum,substract,mul,div}Ogburn
@Ogburn s/substract/subtract/ :p. But thanks for that comment, very useful :). +1.Aerophyte
@Anyplace I did not notice this; but yes it really really is; this is absolutely brilliant. Have a corona free year on you! If I could up vote this 1 time more, I would.Renfro
Note that you can call functions by a pointer without dereferencing it. Some might argue that they want the dereference to be explicit, so they know what they're dealing with. Others would reply that it's a known idiom, and that there isn't much more that p[op]() could ever mean. result = p[op](i, j); works.Mclane
By the way, initializing the array of pointers p[0] = sum and p[0] = &sum are equivalent. Similarly, when calling a function (via a function pointer) you do not need to dereference (*) it... See this stackoverflow question.Doing
@Mclane Thank you for your feedback. I have edited the answer to include an example and your comment, for more visibility.Anyplace
@DanielHeimgartner Thank you for your feedback. I have edited the answer to include an example and your comment, for more visibility.Anyplace
S
62

The above answers may help you but you may also want to know how to use array of function pointers.

void fun1()
{

}

void fun2()
{

}

void fun3()
{

}

void (*func_ptr[3])() = {fun1, fun2, fun3};

main()
{
    int option;


    printf("\nEnter function number you want");
    printf("\nYou should not enter other than 0 , 1, 2"); /* because we have only 3 functions */
    scanf("%d",&option);

    if((option>=0)&&(option<=2))
    { 
        (*func_ptr[option])();
    }

    return 0;
}

You can only assign the addresses of functions with the same return type and same argument types and no of arguments to a single function pointer array.

You can also pass arguments like below if all the above functions are having the same number of arguments of same type.

  (*func_ptr[option])(argu1);

Note: here in the array the numbering of the function pointers will be starting from 0 same as in general arrays. So in above example fun1 can be called if option=0, fun2 can be called if option=1 and fun3 can be called if option=2.

Schram answered 31/10, 2008 at 6:51 Comment(2)
Even for this little demo, you should add a check for the input value, since code targets a newbie... :-)Pogrom
Don't forget #include <stdio.h> at top for newbies like meSaloma
S
11

Here's how you can use it:

New_Fun.h

#ifndef NEW_FUN_H_
#define NEW_FUN_H_

#include <stdio.h>

typedef int speed;
speed fun(int x);

enum fp {
    f1, f2, f3, f4, f5
};

void F1();
void F2();
void F3();
void F4();
void F5();
#endif

New_Fun.c

#include "New_Fun.h"

speed fun(int x)
{
    int Vel;
    Vel = x;
    return Vel;
}

void F1()
{
    printf("From F1\n");
}

void F2()
{
    printf("From F2\n");
}

void F3()
{
    printf("From F3\n");
}

void F4()
{
    printf("From F4\n");
}

void F5()
{
    printf("From F5\n");
}

Main.c

#include <stdio.h>
#include "New_Fun.h"

int main()
{
    int (*F_P)(int y);
    void (*F_A[5])() = { F1, F2, F3, F4, F5 };    // if it is int the pointer incompatible is bound to happen
    int xyz, i;

    printf("Hello Function Pointer!\n");
    F_P = fun;
    xyz = F_P(5);
    printf("The Value is %d\n", xyz);
    //(*F_A[5]) = { F1, F2, F3, F4, F5 };
    for (i = 0; i < 5; i++)
    {
        F_A[i]();
    }
    printf("\n\n");
    F_A[f1]();
    F_A[f2]();
    F_A[f3]();
    F_A[f4]();
    return 0;
}

I hope this helps in understanding Function Pointer.

Sonja answered 22/5, 2012 at 11:7 Comment(3)
Line 15 of Main.c should be for (i = 0; i < 5; i++), right?Barneybarnhart
Why did you declare the fp enumerator?Brasilein
@Arrrow: I think I saw some of the legacy code where they made it in that way... And it looks very beautiful. Just remove f1, f2 ... and in place of then enter 'writefile, readfromfile...'... it becomes more redableSonja
O
9

This "answer" is more of an addendum to VonC's answer; just noting that the syntax can be simplified via a typedef, and aggregate initialization can be used:

typedef int FUNC(int, int);

FUNC sum, subtract, mul, div;
FUNC *p[4] = { sum, subtract, mul, div };

int main(void)
{
    int result;
    int i = 2, j = 3, op = 2;  // 2: mul

    result = p[op](i, j);   // = 6
}

// maybe even in another file
int sum(int a, int b) { return a+b; }
int subtract(int a, int b) { return a-b; }
int mul(int a, int b) { return a*b; }
int div(int a, int b) { return a/b; }
Oribelle answered 28/5, 2014 at 5:4 Comment(1)
Please reserve all caps to pre-processor macros. Many would also advocate created type to end with _t, although this seems controversial for user defined types.Mclane
X
6

Here's a simpler example of how to do it:

jump_table.c

int func1(int arg)  { return arg + 1; }
int func2(int arg)  { return arg + 2; }
int func3(int arg)  { return arg + 3; }
int func4(int arg)  { return arg + 4; }
int func5(int arg)  { return arg + 5; }
int func6(int arg)  { return arg + 6; }
int func7(int arg)  { return arg + 7; }
int func8(int arg)  { return arg + 8; }
int func9(int arg)  { return arg + 9; }
int func10(int arg) { return arg + 10; }

int (*jump_table[10])(int) = { func1, func2, func3, func4, func5, 
                               func6, func7, func8, func9, func10 };
    
int main(void) {
  int index = 2;
  int argument = 42;
  int result = (*jump_table[index])(argument);
  // result is 45
}

All functions stored in the array must have the same signature. This simply means that they must return the same type (e.g. int) and have the same arguments (a single int in the example above).


In C++, you can do the same with static class methods (but not instance methods). For example you could use MyClass::myStaticMethod in the array above but not MyClass::myInstanceMethod nor instance.myInstanceMethod:

class MyClass {
public:
  static int myStaticMethod(int foo)   { return foo + 17; }
  int        myInstanceMethod(int bar) { return bar + 17; }
}

MyClass instance;
Xerxes answered 2/3, 2021 at 22:45 Comment(0)
R
2

Oh, there are tons of example. Just have a look at anything within glib or gtk. You can see the work of function pointers in work there all the way.

Here e.g the initialization of the gtk_button stuff.


static void
gtk_button_class_init (GtkButtonClass *klass)
{
  GObjectClass *gobject_class;
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;

  gobject_class = G_OBJECT_CLASS (klass);
  object_class = (GtkObjectClass*) klass;
  widget_class = (GtkWidgetClass*) klass;
  container_class = (GtkContainerClass*) klass;

  gobject_class->constructor = gtk_button_constructor;
  gobject_class->set_property = gtk_button_set_property;
  gobject_class->get_property = gtk_button_get_property;

And in gtkobject.h you find the following declarations:


struct _GtkObjectClass
{
  GInitiallyUnownedClass parent_class;

  /* Non overridable class methods to set and get per class arguments */
  void (*set_arg) (GtkObject *object,
           GtkArg    *arg,
           guint      arg_id);
  void (*get_arg) (GtkObject *object,
           GtkArg    *arg,
           guint      arg_id);

  /* Default signal handler for the ::destroy signal, which is
   *  invoked to request that references to the widget be dropped.
   *  If an object class overrides destroy() in order to perform class
   *  specific destruction then it must still invoke its superclass'
   *  implementation of the method after it is finished with its
   *  own cleanup. (See gtk_widget_real_destroy() for an example of
   *  how to do this).
   */
  void (*destroy)  (GtkObject *object);
};

The (*set_arg) stuff is a pointer to function and this can e.g be assigned another implementation in some derived class.

Often you see something like this

struct function_table {
   char *name;
   void (*some_fun)(int arg1, double arg2);
};

void function1(int  arg1, double arg2)....


struct function_table my_table [] = {
    {"function1", function1},
...

So you can reach into the table by name and call the "associated" function.

Or maybe you use a hash table in which you put the function and call it "by name".

Regards
Friedrich

Reborn answered 31/10, 2008 at 6:54 Comment(1)
Would it be pssible to use such a function_table for hashing functions within the hash table implementation itself? (Read: circular dependecy involved).Aw
O
2

Can use it in the way like this:

//! Define:
#define F_NUM 3
int (*pFunctions[F_NUM])(void * arg);

//! Initialise:
int someFunction(void * arg) {
    int a= *((int*)arg);
    return a*a;
}

pFunctions[0]= someFunction;

//! Use:
int someMethod(int idx, void * arg, int * result) {
    int done= 0;
    if (idx < F_NUM && pFunctions[idx] != NULL) {
        *result= pFunctions[idx](arg);
        done= 1;
    }
    return done;
}

int x= 2;
int z= 0;
someMethod(0, (void*)&x, &z);
assert(z == 4);
Optician answered 3/6, 2018 at 8:36 Comment(0)
S
1

This should be a short & simple copy & paste piece of code example of the above responses. Hopefully this helps.

#include <iostream>
using namespace std;

#define DBG_PRINT(x) do { std::printf("Line:%-4d" "  %15s = %-10d\n", __LINE__, #x, x); } while(0);

void F0(){ printf("Print F%d\n", 0); }
void F1(){ printf("Print F%d\n", 1); }
void F2(){ printf("Print F%d\n", 2); }
void F3(){ printf("Print F%d\n", 3); }
void F4(){ printf("Print F%d\n", 4); }
void (*fArrVoid[N_FUNC])() = {F0, F1, F2, F3, F4};

int Sum(int a, int b){ return(a+b); }
int Sub(int a, int b){ return(a-b); }
int Mul(int a, int b){ return(a*b); }
int Div(int a, int b){ return(a/b); }
int (*fArrArgs[4])(int a, int b) = {Sum, Sub, Mul, Div};

int main(){
    for(int i = 0; i < 5; i++)  (*fArrVoid[i])();
    printf("\n");

    DBG_PRINT((*fArrArgs[0])(3,2))
    DBG_PRINT((*fArrArgs[1])(3,2))
    DBG_PRINT((*fArrArgs[2])(3,2))
    DBG_PRINT((*fArrArgs[3])(3,2))

    return(0);
}
Southsouthwest answered 28/7, 2016 at 14:43 Comment(2)
If it is a copy&paste from other anwers, I'm not sure it adds any value...Shetrit
Yes I see your point, I will add the value tonight currently at work.Southsouthwest
F
1

The simplest solution is to give the address of the final vector you want , and modify it inside the function.

void calculation(double result[] ){  //do the calculation on result

   result[0] = 10+5;
   result[1] = 10 +6;
   .....
}

int main(){

    double result[10] = {0}; //this is the vector of the results

    calculation(result);  //this will modify result
}
Franko answered 6/2, 2017 at 15:0 Comment(0)
W
0

This question has been already answered with very good examples. The only example that might be missing is one where the functions return pointers. I wrote another example with this, and added lots of comments, in case someone finds it helpful:

#include <stdio.h>

char * func1(char *a) {
    *a = 'b';
    return a;
}

char * func2(char *a) {
    *a = 'c';
    return a;
}

int main() {
    char a = 'a';
    /* declare array of function pointers
     * the function pointer types are char * name(char *)
     * A pointer to this type of function would be just
     * put * before name, and parenthesis around *name:
     *   char * (*name)(char *)
     * An array of these pointers is the same with [x]
     */
    char * (*functions[2])(char *) = {func1, func2};
    printf("%c, ", a);
    /* the functions return a pointer, so I need to deference pointer
     * Thats why the * in front of the parenthesis (in case it confused you)
     */
    printf("%c, ", *(*functions[0])(&a)); 
    printf("%c\n", *(*functions[1])(&a));

    a = 'a';
    /* creating 'name' for a function pointer type
     * funcp is equivalent to type char *(*funcname)(char *)
     */
    typedef char *(*funcp)(char *);
    /* Now the declaration of the array of function pointers
     * becomes easier
     */
    funcp functions2[2] = {func1, func2};

    printf("%c, ", a);
    printf("%c, ", *(*functions2[0])(&a));
    printf("%c\n", *(*functions2[1])(&a));

    return 0;
}
Whatnot answered 31/5, 2016 at 18:22 Comment(0)
A
0

This simple example for multidimensional array with function pointers":

void one( int a, int b){    printf(" \n[ ONE ]  a =  %d   b = %d",a,b);}
void two( int a, int b){    printf(" \n[ TWO ]  a =  %d   b = %d",a,b);}
void three( int a, int b){    printf("\n [ THREE ]  a =  %d   b = %d",a,b);}
void four( int a, int b){    printf(" \n[ FOUR ]  a =  %d   b = %d",a,b);}
void five( int a, int b){    printf(" \n [ FIVE ]  a =  %d   b = %d",a,b);}
void(*p[2][2])(int,int)   ;
int main()
{
    int i,j;
    printf("multidimensional array with function pointers\n");

    p[0][0] = one;    p[0][1] = two;    p[1][0] = three;    p[1][1] = four;
    for (  i  = 1 ; i >=0; i--)
        for (  j  = 0 ; j <2; j++)
            (*p[i][j])( (i, i*j);
    return 0;
}
Annitaanniversary answered 29/12, 2016 at 7:11 Comment(0)
H
-1

Here is the sample code for invoking functions with different signatures with array of pointers.

#include<stdio.h>

#define TOTAL_FUNCTIONS 3

#define FUNCTION_ADD 0
#define FUNCTION_SUBTRACT 1
#define FUNCTION_MULTIPLY 2

int funcAdd(int a, int b, int c)
{
    return a+b+c;
}

void funcSubtract(int a, int b)
{
    printf("\nDiffrence = %d\n",a*b);
}

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


int main()
{
    void* funPtr[3] = {funcAdd, funcSubtract, funcMultiply};

    int result = 0;
    int index = 0;
    while(index < TOTAL_FUNCTIONS){
        switch(index){
            case FUNCTION_ADD:
                result = ((int (*)(int, int, int))funPtr[FUNCTION_ADD])(2,3,4);
                printf("\nSum = %d\n", result);
                break;
            case FUNCTION_SUBTRACT:
                ((void (*)(int, int))funPtr[FUNCTION_SUBTRACT])(5,3);
                break;
            case FUNCTION_MULTIPLY:
                result = ((int (*)(int, int))funPtr[FUNCTION_MULTIPLY])(2,3);
                printf("\nProduct %d\n", result);
                break;
            default:
                break;
        }
        ++index;
    }

    return 0;
}
Hardfavored answered 31/1 at 13:54 Comment(1)
This solution has undefined behavior. C distinguishes between object pointers and function pointers (void * is an object pointer), and C does not allow conversion between them. If you turn compiler diagnostics up to -pedantic level you should see warnings. Such conversion is allowed as a common extension, but not Standard C. But C does allow conversion between function pointers, so instead of an array of void * you could do something like typedef void (GenFunc)(void); /* ... */ GenFunc *funPtr[3] = { (GenFunc *)funcAdd, /* ... */ };.Loydloydie
J
-2
#include <iostream>
using namespace std;
    
int sum (int , int);
int prod (int , int);
    
int main()
{
    int (*p[2])(int , int ) = {sum,prod};
    
    cout << (*p[0])(2,3) << endl;
    cout << (*p[1])(2,3) << endl;
}
    
int sum (int a , int b)
{
    return a+b;
}
    
int prod (int a, int b)
{
    return a*b;
}
Johnjohna answered 8/7, 2021 at 10:45 Comment(1)
The question is asking about C, not about C++. Please, do not provide C++ answers to C questions. Consider answering this question instead if you think that your answers improves on the existing answers.Phina

© 2022 - 2024 — McMap. All rights reserved.