Penguin
Note: You are viewing an old revision of this page. View the current version.

C is probably the only language you can do this in (except maybe Forth). Other languages either have no way of doing this, or don't treat data and code differently. (Feel free to add examples for other languages here.)

Once you've got a pointer to your machine code (usually an array of bytes or ints), you need to cast it to the appropriate type and call it. Eg if you have a pointer to a function which takes a char *, you can call it like this
((int (*)(char *)) p)("hello, world");
The secret here is the parenthesis around the star. To declare a variable to hold the above, use this
int (*func_t)(char *);
Another trick is
typedef int (*func_t)(char *);

int foo(char *x) {

printf("%s",x);

}

func_t p = foo; return p("Narf!");


And you need to do this why?

  • Jon was using it to "compile" something then jump to it in C, by casting an array as a function, then calling it.
  • I use it frequently to do things like have a lookup table of name to function. For example in ircu, there is a function called "parse" which takes a line from a user, splits it up into a function and it's arguments, then scans through a table of functions and their names, when it finds one that matches that command, it calls the function with the arguments it parsed earlier. Nice 'n zippy.
  • Some functions take another function as an argument. Probably the most well-known example is qsort(3) the quick sort algorithm -- you need to pass it an array and a function for comparing array elements. Also see the example below.
from atexit(1)?
  1. include <stdlib.h>

int atexit(void (*function)(void));

you can specify functions to be executed after main() finishes. You do this by calling atexit(functionname), as a function name

without () is a pointer to that function. However, if you want to this for a function that returns something other than null, you have to type cast it. Eg

(int endwin() is an ncurses function).

atexit(endwin);

source.cpp:227: passing `int (*)()' as argument 1 of `atexit(void (*)())'

atexit(void)endwin);

source.cpp:227: void value not ignored as it ought to be

The trick is to cast the pointer to a function pointer of the required type
atexit( (void(*)())endwin );