8

Please give me some examples of jump table usage. I have seen this example on wikipedia:

#include <stdio.h>
#include <stdlib.h>

typedef void (*Handler)(void);    /* A pointer to a handler function */



/* The functions */
void func3 (void) { printf( "3\n" ); }
void func2 (void) { printf( "2\n" ); }
void func1 (void) { printf( "1\n" ); }
void func0 (void) { printf( "0\n" ); }



Handler jump_table[4] = {func0, func1, func2, func3};



int main (int argc, char **argv) {
    int value;

    /* Convert first argument to 0-3 integer (Hash) */
    value = atoi(argv[1]) % 4;
    if (value < 0) {
        value *= -1;
    }

    /* Call appropriate function (func0 thru func3) */
    jump_table[value]();
}

But I was wondering if there is an alternate way of calling the function instead of using index as shown, in the above case it is jump_table[value]();

What I want to achieve is, instead of using the index is there a way to use the name of the function itself.

For example, say we have all the function pointers in a struct.

typedef struct _funcptrs
{
  void func1();
  void func2();
} funcptrs;

and now when I want to call the function can I do something like funcptrs.func1() ?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user1128265
  • 2,891
  • 10
  • 29
  • 34
  • 1
    "using the index is there a way to use the name of the function itself" What you're looking for is either a higher level language or a hash table. The hash table would be string -> function pointer. – Corbin Mar 29 '12 at 19:36
  • 3
    If you want to call with the name of the function itself, then why do you need a jump table in the first place? – Pavan Manjunath Mar 29 '12 at 19:37
  • I didn't actually read your last example, and now that I just did, I believe @PavanManjunath has a point. What exactly are you trying to do? I assumed you wanted to take a char* and call a function based on it. Like how in PHP you can do $func = "strtolower"; echo $func('CORBIN');. – Corbin Mar 29 '12 at 19:39
  • Why would you want to? What would it gain you, but another level of indirection? And what you propose is no longer a jump table. – Mawg says reinstate Monica May 04 '15 at 11:56

3 Answers3

9

You can certainly create a struct containing pointers to functions. There are even good reasons to do so.

For one example, consider the interface between an operating system and a device driver of some sort. Simplifying a lot, this might look something on this order:

struct device { 
    int (*open)(unsigned mode);
    int (*close)(void);
    int (*read)(void *buffer, size_t size);
    int (*write)(void *buffer, size_t size);
};

Then an individual device driver would create a struct of this type, and initialize the individual pointers to refer to the functions relevant to a particular device:

struct device serial_port = { 
    open_serial,
    close_serial,
    read_serial,
    write_serial
};

struct device ethernet_adapter = { 
    open_net,
    close_net,
    read_net,
    write_net
};

struct device keyboard = { 
    open_keyboard,
    close_keyboard,
    read_keyboard,
    NULL  // we'll assume no writing to the keyboard...
};

Then some higher-level function can receive one of these, and open/close/read/write some device without having to know the exact identity of the device involved. Of course, for a real OS, it gets a bit more complex than this but the general idea is (or at least can be) fairly similar.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 2
    +1 - This is very close to what I think the OP is asking. It was a normal technique in the 80's when we lusted after C++ virtual functions, but only had C on PCs. – gbulmer Mar 29 '12 at 20:12
7

Certainly, but you need to declare them as function pointers and initialize them first. Though this defeats the purpose of a jump table if you have to spell out the function name.

e.g.

#include <stdio.h>

void func1 (void) { printf( "1\n" ); }
void func0 (void) { printf( "0\n" ); }

typedef struct
{
  void (*func0)(void);
  void (*func1)(void);
}  funcptrs;

int main(int argc, char *argv[])
{
   funcptrs funcs = { func0, func1 };
   funcs.func1();
   return 0;
}

If you need to call the function by having the name of the function as a string, you need to create a mapping between the functions name and a function pointer, then search the table for that function, and call it.

#include <stdio.h>
#include <string.h>

void func1 (void) { printf( "1\n" ); }
void func0 (void) { printf( "0\n" ); }

#define DEFUN(name) { #name, name }

typedef struct
{
  const char *name;
  void (*func)(void);
}  funcptrs;

void call(funcptrs *ptrs, const char *name)
{
    int i;
    for(i = 0; ptrs[i].name; i++) {
      if(strcmp(ptrs[i].name, name) == 0) {
           ptrs[i].func();
           break;
       }
    }
}
int main(int argc, char *argv[])
{
   funcptrs funcs[] = {DEFUN(func0), DEFUN(func1), {NULL,NULL}};
   call(funcs, "func0");
   return 0;
}
nos
  • 223,662
  • 58
  • 417
  • 506
1

You can use an enum to represent the indices of your array and give them meaningful names for you.

#include <stdio.h>
#include <stdlib.h>

typedef void (*Handler)(void);    /* A pointer to a handler function */

/* The functions */
void func3 (void) { printf( "3\n" ); }
void func2 (void) { printf( "2\n" ); }
void func1 (void) { printf( "1\n" ); }
void func0 (void) { printf( "0\n" ); }

enum{
    FUNC0,
    FUNC1,
    FUNC2,
    FUNC3
};

Handler jump_table[4] = {func0, func1, func2, func3};

int main (int argc, char **argv) {
    /* Call appropriate function (func0 thru func3) */
    jump_table[FUNC0]();
    jump_table[FUNC1]();
    jump_table[FUNC2]();
    jump_table[FUNC3]();
    return 0;
}

This will output

0
1
2
3
Geo
  • 61
  • 5