How can I implement a function lookup table in C? - c

Say I had a program where the user could select a number between 0-10. Each number would then correspond to the calling of a certain function. In Python, I know I could just create an array of function names, index into it with the selected option, and then call the function. How would I implement this in C? Or is it even possible?

Here is an example how to do it. Please note that all functions must have the same signature, but of course you can change that from my funptr type to for example a function that has void return or takes a char and not two ints.
// Declare the type of function pointers.
// Here a function that takes two ints and returns an int.
typedef int (*funptr)(int, int);
// These are the two functions that shall be callable.
int f1(int a, int b) { return a + b; }
int f2(int a, int b) { return a - b; }
// The array with all the functions.
funptr functions[] = {
f1,
f2,
};
// The caller.
int call(int i, int a, int b)
{
return functions[i](a, b);
}

The only problem that I can see in the solution from above is that there is no check for the array index (you may get some tricky problems).
To make the code more robust, you can add a check for the index (boundaries), like
add one if statement inside of function "call" where you check the parameter i (not to be bigger than the maximum value)

Related

When and why should I use void as the return type of a function in C?

I'm currently practising C and learning pointers and arrays. I watched a tutorial where the instructor changed the function from int aFunction() to void aFunction(). Of course, he didn't say why — that's why I'm here. So I'm wondering: when and why should someone use void as the return type for a function.
In C, you have to tell the compiler what are each of the types of the variables you declare. That is why you have things like int and char*.
And functions’ return values are no different. Compiler has to know what each of your functions return types are to work properly. Now if you have a function like add(int a, int b) typically you would want its return type to be of integer, that is why you would define it as
int add(int a, int b)
{
return a+b;
}
Now consider you have a function that doesn’t return anything at all, now you need to tell your compiler that this function returns nothing. That is why void is used. You use void when the function does something but in the end doesn’t need to return any value to the program it was called from. Like this one:
void printAdd(int a, int b)
{
printf(“a + b = %d”, a+b);
}
We are doing a bunch of stuff here but the result from the addition is not returned or stored but rather printed to the screen.
You can use the first function add() like this:
int abc = add(5, 7);
// abc is 12
while you can only use the second function like
printAdd(5, 7);
// you cannot store the value because nothing is returned.
// 5 + 7 = 12 is printed to the screen
The token(s) that precedes the function name in the function declaration is the type of the value that the function returns. In this case there is just one token, but type names may consist of multiple tokens. When you want to return an integer object, you can specify the return type to be int. When the function won't return anything, you use void return type.

const-qualifier with typedef-ed function pointer

What does the C standard have to say regarding typedef-ed function pointers being const qualified in parameters to functions? For example, say I have the following type
typedef int (*Operation)(int a, int b);
I've got a bunch of operations which take two ints, performs the operation, and then returns an int. Then I have a function which performs the actual function pointer call.
int doOpOnce(const Operation op, int a, int b)
{
return op(a, b);
}
I want to guarantee that the function pointer doesn't change during the doOpOnce call and I also want to document to users of doOpOnce that it will actually call the function given to it. Is this valid? Is there any difference between:
int doOpOnce(const Operation op, int a, int b)
int doOpOnce(Operation const op, int a, int b)
Finally, here is an example. Its compiled with gcc 4.9.2 with flags -std=c99 -Wall -Wextra -pedantic and it correctly errors when I try to change my const function pointer.
#include <stdio.h>
typedef int (*Operation)(int a, int b);
int opAdd(int a, int b)
{
return a + b;
}
int opSub(int a, int b)
{
return a - b;
}
int doOpOnce(const Operation op, int a, int b)
{
op = opSub; // error: assignment of read-only parameter 'op'
return op(a, b);
}
int main()
{
printf("%d\n", doOpOnce(opAdd, 10, 20));
return 0;
}
I do not want to add the const qualifier to the Operation typedef as I have other functions which CAN modify Operation pointers. I just want stronger typing in some circumstances.
If the parameter type is Operation, the caller passes a copy of the pointer into the function and so the function can't actually change where that pointer is pointing back in the caller. Adding the const keyword here would just be a defensive technique in the implementation that prevents you from reassigning your local copy. In that sense, you probably don't even need the const qualifier to signal anything to the client of your library.
To address your other question, the two placements of const have the same meaning, so you can pick whichever one you'd like.
Let the outside world (.h) see int doOpOnce(Operation op, int a, int b); and your .c file implement int doOpOnce(Operation const op, int a, int b) { so "to guarantee that the function pointer doesn't change during the doOpOnce"
"I also want to document to users of doOpOnce that it will actually call the function given to it. " belongs in the code documentation.
A function declaration signature of int doOpOnce(Operation const op, int a, int b); is not sufficient to guarantee "it will actually call the function given to it".
For the user of the function doOpOnce it is unimportant whether the pointer to function declared with the const qualifier or not because the function deals with a copy of the original pointer supplied by the user as an argument.
For the user of the function these two function declarations
int doOpOnce(const Operation op, int a, int b);
and
int doOpOnce( Operation op, int a, int b);
declare the same one function. You may include the both declarations in the program.
It is only within the function definition you will not be able to change this pointer that is a local variable of the function as any its parameter.
.

Container to save function pointer

I need a container to save function pointers to certain numbers.
Like
1 = function add
2 = function sub
3 = function mult
And so on. This is for a simple interrupt handler, where depending on the interrupt number a certain function should be called.
I thought that I can do this with a structured list, but I know the size of the maximal amount of entries. So I thought about an array of strings like
const char *functions[2];
a[0] = "add";
a[1] = "sub";
But then I don't know how I can further use the strings.
Any tips or thoughts?
Thanks in advance!
EDIT: To clarify, I have 2 important functions here, one, where I want to save a function pointer together with a number into some container. And another one, which just says "goto the function which is at a certain number in that container". So the first function gets an int number (say from 1 to 50) and a pointer to a function. Those should be saved together. The second function then just gets an int number as parameter and then it should call the function which is associated with that int number in my container. What I'm asking is how I could save a pointer that points to a function together with a number.
EDIT2: I do want to save function pointers. I thought I could maybe save the function name as a string and then use it later as function name because I didn't know another way.
If you want to store and use a function pointer you can do it like this:
// the functions you want to point to
int add(int a, int b) { do stuff }
int sub(int a, int b) { do some other stuff }
...
// declare and set a function pointer
int (*myFuncPtr) (int, int);
myFuncPtr = ⊂ // points to the function "sub". The & is optional
// now use it:
int result = myFuncPtr(23, 42);
The type of a function pointer depends on the return value and the parameters of the function you want to point to.
You can make the declaration of a function pointer variable easier
by using typedef:
typedef int (*funcPtr) (int, int);
Now declare and initialize a function pointer using the typedef like this:
funcPtr myFuncPtr = &add;
Of course you can now put many of those pointers into an array
and access them by the indices:
funcPtr funcPtrs[] = { &sub, add }; // like i said, the ampersand is optional
int result = funcPtrs[0](23, 42);
You have to store function pointers, so define a new function pointer type and make an array. According to your question the all functions should take two int parameters and return and int, so the new type should be something like this:
typedef int (*operation_t)(int,int);
Now you can create an array of operation_t. The whole code:
#include <stdio.h>
typedef int (*operation_t)(int,int);
int addInt(int n, int m) {
return n+m;
}
int subInt(int n, int m) {
return n-m;
}
int multipleInt(int n, int m) {
return n*m;
}
int main ()
{
const operation_t function_list[3] = {&addInt, &subInt, &multipleInt};
int i;
for(i = 0; i < 3; i++)
{
printf("inputs: 2 and 3 result: %d\n", function_list[i](2,3));
}
return 0;
}
The output:
Note that, as it's an array the indexes are 0, 1, 2.
To add an own ID you can create a stuct with the function pointer and an int ID.
typedef struct operation
{
int (*operation_p)(int,int);
int id;
} math_operation_t;
You can even build a linked list, and add functions dynamically if you define a third member variable, which should be the pointer to the next element.

function pointer with variable inputs

In C, I am trying to pass a single-variable function into an optimization routine (optimization_routine). The optimization routine takes as input a pointer func1ptr to a function of a single float variable. However, I need to be able to pass multiple variables into this function. Thus, I am trying to construct a function pointer of one variable where all but the first inputs are "constants" into the function variable (sort of analogous to a partial derivative in calculus). I think I can do this with function pointers, but I can't figure out a syntax that makes sense.
That is, I have a function like this:
float function_all_inputs( float A, int B, float C, char D);
The optimization function requires a pointer like this:
typedef (*func1ptr)(float);
void optimization_function( func1ptr fp );
Thus, I want to construct a function of this form:
// create a function of A only at runtime using inputs B,C,D
func1ptr fp = ( & function_all_inputs(A,B,C,D))(A);
The function pointed to by fp should have the signature:
float function_one_input(float A);
Inputs B, C, and D are calculated elsewhere in the code, and thus are not known at compile-time; however, they are constant inside optimization_function.
I think I can do this in pure C using function pointers, however, I can't figure out the correct syntax. None of the examples I found online cover this case. Any advice you can provide would be appreciated.
It sounds like you are asking how to create a closure to capture parameters in C, and you can take a look at some options in the linked question.
However, without custom extensions, I think you will need to use global variables to achieve the effect you are looking for.
// Pass this wrapper with the name "wrapper" into the function
// that requires a function pointer
void wrapper(float a) {
// Where last four arguments are global variables that are computed first.
function_all_inputs(a, b, c, d, e);
}
// No need to create an explicit function pointer.
// Passing the name of the function is sufficient.
optimization_function(wrapper);
You need to write a wrapper function, like
int b;
float c;
char d;
int wrap(float a) {
return function_all_inputs(a, b, c, d);
}
Consider concurrency an re-entrancy though:
If multiple threads can use the wrapper, and need it to pass different data, make those globals thread-local:
_Thread_local int b;
If you need full re-entrancy, things get complicated:
You need to (also) save the variables before using a nested invocation with different parameters.
Writing a second (and maybe third) version of the wrapper using different globals may be better.
If you need more active at the same time, you can try a pool of those functions, though it gets unwieldy really fast. Better change your optimization-function by adding a context-parameter, and pass those extra-parameters with that.
For full freedom, you really need a way to write functions at runtime, at least enough to recover a context-pointer. That's not possible in pure C though.
If sizeof(float) >= sizeof(void*) on your platform, then you can "hack" it as follows:
typedef struct
{
float a;
int b;
float c;
char d;
}
params;
int function_all_inputs(float a, int b, float c, char d)
{
...
}
int function_one_input(float f)
{
params* p;
memcpy((void*)&p, (void*)&f, sizeof(void*));
return function_all_inputs(p->a, p->b, p->c, p->d);
}
int optimize()
{
float f;
params v;
params* p = &v;
v.a = ...;
v.b = ...;
v.c = ...;
v.d = ...;
memcpy((void*)&f, (void*)&p, sizeof(void*));
return optimization_function(function_one_input, f);
}
You weren't very consistent in your question about the return-value type, so I used int.
This may be overkill, but libffi supports creating closures in the following way:
#include <stdio.h>
#include <ffi.h>
typedef struct BCD { int B; float C; char D; } BCD;
void function_one_input_binding
(ffi_cif* cif, int* result, void** args, BCD* bcd) {
*result = function_all_inputs(*(float*)args[0], bcd->B, bcd->C, bcd->D);
}
int main() {
ffi_cif cif;
ffi_type* args[1];
ffi_closure* closure;
int (*function_one_input)(float);
// Allocate a closure.
closure = ffi_closure_alloc(sizeof(ffi_closure), &function_one_input);
// Tell libffi the parameter and return types.
args[0] = &ffi_type_float;
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_int, args);
// Bind closure data.
BCD bcd = { .B = 1, .C = 2.5, .D = 'x' };
ffi_prep_closure_loc(
closure, &cif, function_one_input_binding, &bcd, function_one_input);
// Call the function.
int result = function_one_input(42.5);
// Free the allocated closure.
ffi_closure_free(closure);
return 0;
}

How to define an array of function pointers and the functions don't have same input argument definition?

Is it possible to define an array of function pointers (and the functions don't have se same input argument ) as indicating in the following code ?
If yes what I have to put in the function definition int (*handler)(/*what Ihave to put here ?*/);
struct handler_index {
const char *name;
int (*handler)(/*what Ihave to put here ?*/);
};
int handler0 (int a, int b)
{
printf("%d\n",a+b);
}
int handler1 (int a, int b, int c)
{
printf("%d\n",a+b+c);
}
int handler2 (int a, int b, int c, int d)
{
printf("%d\n",a+b+c+d);
}
const struct handler_index handler_index[] = {
[0] = {"handler0", handler0},
[1] = {"handler1", handler1},
[2] = {"handler2", handler3},
};
Just put nothing:
int (*handler)();
it means the function has an unspecified (but non-variable) number and types of parameters.
Any function that returns an int and with a fixed variable number of parameters can be assigned to handler.
Whilst int (*handler)() will indeed allow variable number of arguments for th function, I fail to see any benefit in this. Function pointers are useful when you have a piece of code that takes something, finds the "right thing to do" (e.g comparing the "name" with some input from elsewhere), and calls the function pointer to do whatever it has to do. The function pointer calling code needs to know how many arguments the function has (how else would it pass the right number and order of arguments.
I don't actually see any meaningful use of this at all. Yes, you can pass a variable number of arguments to a function, but the code HAS to know what arguments the function takes.
Unless the arguments are somehow specified in the definition of the struct - but then you need to define different content for the struct to allow for that.
I would suggest that you need to think about what you are trying to achieve, and then come up with a solution to the problem, most likely using a different method.
Put nothing. Just empty brackets.
int (*handler)();

Resources