i'm trying to implement a simple array of function descriptors of type fun_desc
struct fun_desc {
char *name;
void (*fun)();
};
i have 2 function f1 and f2 both are of type coolFunct
typedef int (*coolFunct) (unsigned int);
my array is defined as follows
struct fun_desc funArr[]={{"f1", &f1}, {"f2",&f2}};
now i am trying to call a function in the array, i presume i need to cast it to coolFunct because it is of unspecified type (or am i wrong)
but the next call doesn't work (no compile or runtime error, just nothing happens) :
((coolFunct)(funArr[0].fun))(1);
as always help is greatly appreciated thanks ...
Use this syntax:
(*funArr[0].fun)();
Also, don't cast, your function types differ and things will crash, try this:
typedef int (*coolFunct) (unsigned int);
struct fun_desc {
char *name;
coolFunct fun;
};
(*funArr[0].fun)(1);
EDIT: If you actually want to cast, the syntax for calling is:
((coolFunct)funArr[0].fun)(1);
You need to cast the function pointers when you store them in the struct. Your compiler is supposed to give you a diagnostic for this. It's hard to see how it could be the source of your problems though.
#include <stdio.h>
typedef int (*coolFunct) (unsigned int);
typedef void (*whackFunct)();
int f1(unsigned i) { puts("f1"); return 1; }
int f2(unsigned i) { puts("f2"); return 2; }
struct fun_desc {
char *name;
void (*fun)();
};
struct fun_desc funArr[]={{"f1", (whackFunct)&f1}, {"f2", (whackFunct)&f2}};
int main()
{
printf("function returned %d\n", ((coolFunct)funArr[0].fun)(1));
return 0;
}
Related
can you please explain in details this line of code inside struct:
There is a pointer to function but why would you reference it to struct?
void (*function)(struct Structure *);
what does this mean
(struct Structure *)?
(struct Structure *)
It means that the function have a struct Structure * argument. Actually it will make more sense with (struct Structure *variable of struct).
In this way, you can use a pointer to point a struct and should put the address of the struct variable which can be used in the function.
#include <stdio.h>
typedef struct circle{
int rad;
int area;
} Circle;
void ShowCircleInfo(Circle *info)
{
printf("rad value: %d\n", info->rad);
printf("area value: %d", info->area);
}
int main(void)
{
Circle circle_one;
circle_one.rad = 2;
circle_one.area = 3;
ShowCircleInfo(&circle_one);
return 0;
}
void (*function)(struct Structure *); declares function to be a pointer to a function that has a parameter of type struct Structure * and does not return a value.
For example
#include <stdio.h>
struct Structure {
int a;
void (*function)(struct Structure *);
};
void foo(struct Structure *a) {
if (a->function == NULL) a->function = foo;
a->a++;
printf("%d\n", a->a);
}
int main(void) {
struct Structure a = {42, foo};
struct Structure b = {0}; // don't call b.function just yet!!
a.function(&b); // foo(&b)
b.function(&a); // foo(&a)
}
See code running at https://ideone.com/7E74gb
In C, function pointer declarations have almost the same structure as function headers.
Only the function name will change to have some parantheses and a "*" in it, and the arguments won't have names, because only their types are important when using pointers (we don't access the values of the arguments, so we don't need their names).
They basically look like this:
<return_value> (*<function_name>)(<argument_list>)
So, for example, the function pointer for the function
void swap(int* a, int* b);
would be
void (*swap_ptr)(int*, int*);
Notice that the name of the pointer is in the place of the name of the function, and looks a bit odd compared to normal pointer declarations.
An excellent reading on this topic (you can skip the C++ stuff): https://www.cprogramming.com/tutorial/function-pointers.html
I declared a struct like this one :
typedef struct s_data {
char buff[2048];
int len;
void *func[10];
struct data *next;
} t_data;
In my code, when passing a *data, I assigned some functions (just giving one so it is more understandable)
void init_data(t_data *data)
{
data->len = 0;
data->func[0] = &myfirstfunctions;
//doing the same for 9 others
}
My first function would be something taking as argument *data, and an int.
Then, I try to use this function in another function, doing
data->func[0](data, var);
I tried this and a couple of other syntaxes involving trying to adress (*func[0]) but none of them work. I kind of understood from other much more complex questions over there that I shouldn't store my function like this, or should cast it in another typedef, but I did not really understand everything as I am kind of new in programming.
void* can only be used reliably as a generic object pointer ("pointer to variables"). Not as a generic function pointer.
You can however convert between different function pointer types safely, as long as you only call the actual function with the correct type. So it is possible to do just use any function pointer type as the generic one, like this:
void (*func[10])(void);
...
func[0] = ((void)(*)(void))&myfirstfunction;
...
((whatever)func[0]) (arguments); // call the function
As you might note, the function pointer syntax in C is horrible. So I'd recommend using typedefs:
typedef void genfunc_t (void);
typedef int somefunc_t (whatever*); // assuming this is the type of myfirstfunction
Then the code turns far easier to read and write:
genfunc_t* func [10];
...
func[0] = (genfunc_t*)&myfirstfunction;
...
((somefunc_t*)func[0]) (arguments);
If all of your functions will have the same signature, you can do this like:
#include <stdio.h>
typedef void (*func)(void *, int);
struct s_data {
char buff[2048];
int len;
func f[10];
struct s_data *next;
};
static void
my_first_function(void *d, int x)
{
(void)d;
printf("%d\n", x + 2);
}
static void
init_data(struct s_data *data)
{
data->len = 1;
data->f[0] = my_first_function;
}
int
main(void)
{
struct s_data d;
init_data(&d);
d.f[0](NULL, 5);
return 0;
}
If your functions have different signatures, you will want to either use a union, or perhaps you will need several different members of the struct to store the function pointers.
The problem is that you haven't actually declared an array of function pointers. What you actually did is an array of pointers to void.
The syntax of declaring a pointer to function is as following:
function_return_type (*pointer_name)(arg1_type,arg2_type,...);
Then you can create an array of pointers to functions:
function_return_type (*arr_name[])(arg1_type, arg2_type,...)
Therefore, the declaration of your structure should look like this:
typedef void (*pointer_to_function)(void *, int);
struct s_data {
char buff[2048];
int len;
pointer_to_function array_of_pointeters[10];
struct s_data *next;
};
Good luck:)
Can we have functions in structures in C language?
Could someone please give an example of how to implement it and explain?
No, structures contain data only. However, you can define a pointer to a function inside of a struct as below:
struct myStruct {
int x;
void (*anotherFunction)(struct foo *);
}
The answer is no, but there is away to get the same effect.
Functions can only be found at the outermost level of a C program. This improves run-time speed by reducing the housekeeping associated with function calls.
As such, you cannot have a function inside of a struct (or inside of another function) but it is very common to have function pointers inside structures. For example:
#include <stdio.h>
int get_int_global (void)
{
return 10;
}
double get_double_global (void)
{
return 3.14;
}
struct test {
int a;
double b;
};
struct test_func {
int (*get_int) (void);
double (*get_double)(void);
};
int main (void)
{
struct test_func t1 = {get_int_global, get_double_global};
struct test t2 = {10, 3.14};
printf("Using function pointers: %d, %f\n", t1.get_int(), t1.get_double());
printf("Using built-in types: %d, %f\n", t2.a, t2.b);
return 0;
}
A lot of people will also use a naming convention for function pointers inside structures and will typedef their function pointers. For example you could declare the structure containing pointers like this:
typedef int (*get_int_fptr) (void);
typedef double (*get_double_fptr)(void);
struct test_func {
get_int_fptr get_int;
get_double_fptr get_double;
};
Everything else in the code above will work as it is. Now, get_int_fptr is a special type for a function returning int and if you assume that *_fptr are all function pointers then you can find what the function signature is by simply looking at the typedef.
No, it has to be implemented like this :
typedef struct S_House {
char* name;
int opened;
} House;
void openHouse(House* theHouse);
void openHouse(House* theHouse) {
theHouse->opened = 1;
}
int main() {
House myHouse;
openHouse(&myHouse);
return 0;
}
struct MyStruct
{
int i;
double arr[10];
};
struct MyStruct func()
{
};
When returned from the function, will be fully copied to a local variable?
struct Mystruct ms = func();
Yes you can, the structure will be fully copied.
Yes, if func() returns a variable of type Mystruct.
The correct way to do this:
void func(struct MyStruct* by_ref);
int main()
{
struct MyStruct ms;
func(&ms);
}
This won't upload a bombastic struct on the stack, nor will you get issues with static variables. Returning a pointer to a static variable is very bad for the following reasons:
It breaks private encaptulation. Very bad program design.
A multi-threaded program doing this gets vulnerable.
Pure bugs, as in this example:
static uint8 static_str[6];
uint8* func(const uint8 str[6])
{
uint8 i;
for(i=0; i<6; i++)
{
static_str[i] = str[i];
}
return static_str;
}
int main()
{
print_strings(func(“hello”), func(“world”));
}
The output from a function printing the two strings will be either “hello hello” or “world world” (depending on the order of evaluation of function parameters).
You have no return value so in any case you need to set that. Furthermore, it is better to use a pointer:
struct MyStruct* func()
{
struct MyStruct *pMyStruct=calloc(1,sizeof(struct MyStruct));
/* fill struct */
return pMyStruct;
};
I am working on a program in C and using the SDCC compiler for a 8051 architecture device.
I am trying to write a function called GetName that will read 8 characters from Flash Memory and return the character array in some form. I know that it is not possible to return an array in C so I am trying to do it using a struct like this:
//********************FLASH.h file*******************************
MyStruct GetName(int i); //Function prototype
#define NAME_SIZE 8
typedef struct
{
char Name[NAME_SIZE];
} MyStruct;
extern MyStruct GetName(int i);
// *****************FLASH.c file***********************************
#include "FLASH.h"
MyStruct GetName( int i)
{
MyStruct newNameStruct;
//...
// Fill the array by reading data from Flash
//...
return newNameStruct;
}
I don't have any references to this function yet but for some reason, I get a compiler error that says "Function cannot return aggregate." Does this mean that my compiler does not support functions that return structs? Or am I just doing something wrong?
SDCC doesn't support assignment and returning structs yet (if their Wiki is up-to-date):
Not yet implemented in sdcc:
Data type double.
Structures and unions can not be assigned, passed as function parameters or return values.
register storage class specifier in function parameters.
Maybe you should make a
void GetName(MyStruct* ret_name, int i);
function instead.
That said, you should put the function prototype before the main and after the MyStruct. If there's no prototypes a function will be assumed to return int.
MyStruct GetName(int i);
void main(void) { ...
(Also, the main function should be an int main(void) or int main(int argc, char** argv). It shouldn't return void.)
All post-ANSI C89/90 compilers allow returning struct objects. Classic (pedantic) K&R C compilers do not.
However, in any case you have to declare the function first. i.e. before you call it. And char[8] Name inside your struct is not a valid declaration. The valid form is char Name[8].
Your pointer-to-array-returning function is declared correctly. It is your size macro that's broken. Should be
#define NAME_SIZE 8
Note: no = character.
Yes, functions can return structs in C. Your code above has several errors. With a few changes, It compiles correctly under gcc (I don't have sdcc installed to try with, but please try the code below.
struct MyStruct
{
char Name[8];
};
struct MyStruct GetName( int i)
{
struct MyStruct newNameStruct;
//...
// Fill the array by reading data from Flash
//...
return newNameStruct;
}
int main(void)
{
int NameIndex = 3;
struct MyStruct testStruct;
testStruct = GetName(NameIndex);
return 0;
}
I really wouldn't want to use a C compiler that didn't implement structure call and return by value, as KennyMT suggests yours doesn't. In fact, such a compiler should not really be called a C compiler. If the compiler implements structures at all, return by value is not hard to implement.
Anyway, to work with your compiler you will want something like:
typedef struct
{
char Name[NAME_SIZE];
} MyStruct;
void f( MyStruct * m ) {
strcpy( m->Name, "foo" );
}
int main() {
MyStruct ms;
f( & ms );
return 0;
}