Hey guys I have a question: How can i call a function from an enum structure with pointers?
For example I have this structure:
typedef enum struct_e
{
FUNCTION_ONE,
FUNCTION_TWO,
FUNCTION_THREE,
FUNCTION_FOUR,
} sctruct_t;
And I have a function that receives one of these variables and the parameters of the function (for example an int)
void call_functions(struct_t action, int exemple) {...}
// -> call like this call_functions(FUNCTION_ONE, 45);
And in that function I have to call one of the functions like this one:
void function_one(int a)
{
printf("You have %d years old", a);
}
Assuming each of the functions to call has type void (*)(int), you can create an array of function pointers, using the enum values as the array index:
typedef void (*call_func_type)(int);
call_func_type func_list[] = {
[FUNCTION_ONE] = function_one,
[FUNCTION_TWO] = function_two,
[FUNCTION_THREE] = function_three,
[FUNCTION_FOUR] = function_four
}
Then call_functions would just index into that array:
void call_functions(struct_t action, int example)
{
func_list[action](example);
}
I usually find that the first step when dealing with a function pointer is to use a typedef to make the syntax more readable. Then, such pointers can be used much like any other data type.
// declares function_ptr as a new type, pointer to function taking an integer parameter and returning void
typedef void (*function_ptr)(int);
// define function pointer p and initialize to point at function one
function_ptr p = function_one;
// call function_one passing 7 as a parameter
(*p)(7);
In this case, assuming that all of the functions take an integer as a parameter, we can use a table of pointers to represent all the functions you'd want to call:
function_ptr table[]=
{
function_one,
function_two,
function_three,
function_four,
};
At this point it's fairly easy to call any number of functions using this method.
void call_functions(struct_t action, int exemple)
{
if( action >= FUNCTION_ONE && action <= FUNCTION_FOUR )
{
(table[action])(exemple);
}
else
{
printf("Unrecognized function %i. Check that function table is up to date\n", (int)action);
}
}
Related
Alright, this is my first post ever in StackOverflow, I have TRIED everything for this. So first instruction is that I need to make a function pointer inside a struct. No problems so far with that.
typedef struct Function2D {
float (*Fun2D) (float);
}Function2D;
The teacher wants this struct function pointer to multiply a given float number by two. I already did that.
int main()
{
Function2D Funcion;
Funcion.Fun2D = Test;
Funcion.Fun2D(10000);
return 0;
}
float Test (float n)
{
n = n*2;
return n;
}
However I the teacher wants to implement another function that returns a Boolean after getting a data type Function2D or the result of the multiplication. Is there a way to access the result of the function pointer from a struct without hardcoding a value?
If I understand your question correctly, then you are asking how to implement a function
returning a bool that takes a function as an argument
OR
that takes a structure containing function pointers as an argument.
OR
that pass the result from a call to a function pointer to another function.
Here is an example all three:
#include <stdio.h>
// Define the types for the function pointers you need
typedef float (*FloatFunc) (float);
typedef bool (*BoolFunc) (FloatFunc);
// Declare a structure containing each of the function pointer types defined above.
typedef struct StructContainingFunctionPointers {
FloatFunc FunFloat;
BoolFunc FunBool;
} StructContainingFunctionPointers;
// Declare a function of the same type as FloatFunc
float MultiplyBy2(float n)
{
n = n * 2;
return n;
}
// Declare a function of the same type as BoolFunc
bool TestIfMultiplyBy2(FloatFunc func)
{
return func(2) == 4;
}
// Declare a function that takes StructContainingFunctionPointers as an argument
void TestStructContainingFunctionPointers(StructContainingFunctionPointers Rec) {
// Do a smoke-test of FunFloat
float result = Rec.FunFloat(10000);
// Pass the result of Rec.FunFloat to printf()
printf("Calling FunFloat(10000) returned %.0f.\n", result);
if (result == 10000 * 2)
printf("The float function seems to work.\n");
else
printf("The float function DOES NOT work.\n");
// Do a smoke-test of FunBool
if (Rec.FunBool(Rec.FunFloat))
printf("The bool function seems to work.\n");
else
printf("The bool function DOES NOT work.\n");
}
int main()
{
// Initialize the record.
StructContainingFunctionPointers Rec;
Rec.FunFloat = MultiplyBy2;
Rec.FunBool = TestIfMultiplyBy2;
// Test
TestStructContainingFunctionPointers(Rec);
// Return success
return 0;
}
This is the output from the program:
Calling FunFloat(10000) returned 20000.
The float function seems to work.
The bool function seems to work.
Main use of function pointers (from what I gather) is to pass them along with some variables to a function which will then call the function the pointer points to. To achieve similar results one can pass an arbitrary integer instead of a function pointer and let a switch case call the appropriate function; which will also bypass the restriction that is innate to function pointers, that a function you are passing the pointer to, needs to know exactly what kind of function is coming to it (what it returns and what variables it expects.)
Is there an advantage to using function pointers over the switch case method proposed above? I'm interested in technical capabilities of function pointers that I might be missing and preferably some examples too.
If the functions each have different signatures, you'll need to have a separate case for each one in order to call the right parameters and get the right return type.
If the signatures are the same, you could instead create an array of function pointers and just index the array. This avoids branches and is simpler to maintain. For example:
int add(int, int);
int sub(int, int);
typedef int (*math_func)(int, int);
math_func arr[] = { add, sub };
int call_math_func(int idx, int a, int b)
{
return math_func[idx](a, b);
}
I prefer using function pointers when possible because imho they make intents more explicit at the calling site, e.g.:
#include <stdio.h>
typedef void (*HelloWorld)(void);
void english(void) { printf("Hello, World!\n"); }
void italian(void) { printf("Ciao, Mondo!\n"); }
void greet_world_in(HelloWorld hello_world) { hello_world(); }
int main(void)
{
greet_world_in(english);
greet_world_in(italian);
return 0;
}
Assuming that the function pointers have exactly the same kind of prototype, a switch case statement is often implemented as a jump table:
void conceptual_dispatcher_emulating_switch_case(int n) {
static const jmp_ptr_t jmp_table[5]={label_0,label_1,label_2,label_3,label_4};
if (n < 5) {
goto jmp_table[n];
}
return;
label_0 : return myfunc_1();
label_1 : return myfunc_2();
label_2 : return myfunc_3();
label_3 : return myfunc_4();
label_4 : return myfunc_5();
}
From this it's pretty easy to make an optimization:
void conceptual_dispatcher_better(int n) {
static const function_ptr_t jmp_table[5]={myfunc_1, myfunc_2, myfunc_3, myfunc_4, myfunc_5};
if (n < 5) {
goto jmp_table[n];
}
return;
}
And from this the next logical step is to
void conceptual_dispatcher_even_better(function_ptr_t *ptr) {
ptr();
}
And from this the next step is to make that inline or just call the ptr without the dispatcher.
I want to have a function that returns a function that is called without an argument, even though the original function must be called with an argument. The argument is passed to the first function and will be implicitly used each time a call to the returned function is made.
I am aware of function pointers in C but I don't know if they can be used in such a way. I know how to do this in python as shown in the following sample code :
def foo(some_argument):
print(some_argument)
def register_callback(function, argument):
def new_function():
function(argument)
return new_function
bar = register_callback(foo,"bar")
bar()
From what I read, this way is not possible in C because we can't nest function definitions. Is this possible and if so what would be the proper way to do it?
About all you can do in C is create a record (a struct) containing both the function pointer and the argument to pass and then use that record as the “thing” that is called, with the assistance of a wrapper function that does the actual calling.
#include <stdio.h>
typedef int SomeType; // Sample type for demonstration.
// Define a record to hold a function pointer and the argument we want to pass.
typedef struct
{
void (*Function)(SomeType); // Function to call.
SomeType Argument; // Argument to pass.
} Closure;
// Define some sample functions.
static void A(SomeType x) { printf("Called %s(%d).\n", __func__, x); }
static void B(SomeType x) { printf("Called %s(%d).\n", __func__, x); }
// Define a function that returns a closure.
static Closure foo(int Which, SomeType x)
{
return (Closure) { .Function = Which & 1 ? B : A, .Argument = x };
}
// Define a function to call a closure.
static void Call(Closure C) { C.Function(C.Argument); }
int main(void)
{
Closure a = foo(0, 34);
Closure b = foo(1, 79);
Call(a);
Call(b);
}
Output:
Called A(34).
Called B(79).
I am having troubles formulating my objective in words so I am not too sure on how to express this.
Say I have two functions with the following signatures:
myBigStruct_t function1()
int function2()
with a definition of myBigStruct_t (that stores a lot of data and is somewhere else) and a union definition that can support the size of both return types:
typedef union myUnion{
myBigStruct_t A;
int B;
} myData_t;
union my2ndUnion{
myData_t data_;
char myArray[sizeOf(myData_t)];
} un2;
Can I do the following:
un2.myArray = function1();
...
if( something ){
myExpress = un2.data_.A;
else{
myOtherExpress = un2.data_.B;
}
...
un2.myArray = function2();
if( something ){
myExpress = un2.data_.A;
else{
myOtherExpress = un2.data_.B;
}
I know array data is normally passed by reference but most C compilers have a means of passing large data types that at least appear to be by value (regardless of whether or not a secret pointer is used).
I know its a bit contrived; I am just trying to get my ahead around unions.
Yes, that is exactly what unions do. I think that answers your question (let me know if it doesn't), but I'll give some more background.
If myBigStruct_t is defined like this:
typedef struct {
char someChars[256];
int someInts[512];
} myBigStruct_t;
Then when you do the assignment from function1(), the data is copied. There is no secret pointer involved.
On the other hand, if myBigStruct_t is defined like this:
typedef struct {
char *someChars; //This gets malloc'd in function1
int *someInts; //This gets malloc'd in function1
} myBigStruct_t;
Then the data is passed by reference, i.e. the data was not copied.
Note that your code as-is won't work because of the type mismatch between the return values of function1 and myArray, and the same for function2. You'll have to assign the specific union members:
un2.myArray.data_.A = function1();
un2.myArray.data_.B = function2();
I don't think there's any reason not to do it this way.
Edit (in response to your comment):
Why not just pass the array as a parameter instead of return value? A function prototype would be like: void foo(void* buffer, size_t buffer_len). I assume you fully understand pointers (otherwise function pointers are probably not the right way to solve your problem). A complete program might look like:
//All the functions use this prototype, although it isn't strictly necessary (your loop would just have to be smarter)
typedef void(*GenericFunctionCall)(void* buffer, size_t buffer_len);
//A struct with only a few bytes
typedef struct SmallStruct_s{
char value;
} SmallStruct_t;
//A struct with more bytes
typedef struct BigStruct_s {
char value[1024];
} BigStruct_t;
//Defining this makes it easy to get the maximum size of all the structs
typedef union AllStructs_s {
SmallStruct_t small;
BigStruct_t big;
} AllStructs_t;
//This function takes the buffer, casts it to a SmallStruct_t, and then does something with it (presumably sets param->value to something)
void smallFunction(void* buffer, size_t buffer_len) {
SmallStruct_t * param = (SmallStruct_t*)buffer;
//do something with param
}
//This function does the same with BigStruct_t
void bigFunction(void* buffer, size_t buffer_len) {
BigStruct_t * param = (BigStruct_t*)buffer;
//do something with param
}
int main() {
//This allocates memory for all the values generated by smallFunction and bigFunction.
AllStructs_t param;
//This is your table of function pointers
GenericFunctionCall functions[2];
functions[0] = smallFunction;
functions[1] = bigFunction;
//Loop through the functions and do something with the results
for (uint32_t function_index = 0; function_index < 2; ++function_index) {
functions[function_index]((void*)¶m, sizeof(AllStructs_t));
//Do something with param here
}
}
Second edit:
Okay I now see what you're trying to do. You can't use union between to accept an arbitrary value, in this case unions are no different from any other data type (i.e. I can't assign BigStruct_t = SmallStruct_t).
Here's why: when the compiler generates code to handle the return value of a function, it is using the caller's memory to store the value. Because of that, you're not allowed to get a pointer to the return value for a function. In compiler-speak: the return value of a function is not an lvalue. The options for solving this are:
Store the return type of the function in the table, and use that assign the appropriate variable
Write a wrapper function for each function from the table, and have it convert the return type from return value to pointer parameter. Call the wrapper instead of the original function
Refactor the code completely
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.