Casting a void pointer to a struct - c

I started feeling comfortable with C and then I ran into type casting. If I have the following defined in an *.h file
struct data {
int value;
char *label;
};
and this in another *.h file
# define TYPE void*
How do I cast the void pointer to the struct so that I can use a variable "TYPE val" that's passed into functions? For example, if I want to utilize the value that TYPE val points to, how do I cast it so that I can pass that value to another functions?

(struct data*)pointer
will cast a pointer to void to a pointer to struct data.

Typecasting void pointer to a struct can be done in following
void *vptr;
typedef struct data
{
/* members */
} tdata;
for this we can typecast to struct
lets say u want to send this vptr as structure variable to some function
then
void function (tdata *);
main ()
{
/* here is your function which needs structure pointer
type casting void pointer to struct */
function((tdata *) vptr);
}
Note: we can typecast void pointer to any type, thats the main purpose of void pointers.

Related

Using a function from a function array stored in a struct in C

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:)

Trying to call function using a void pointer inside a variable type

In the firmware that I am writing, I created a type of variable. Similar to what is below:
struct SitemMenu {
unsigned int id;
char * text;
void * submenu
}
typedef struct SitemMenu TitemMenu;
Be any function:
void functionX () {
...
}
If I create this variable:
TitemMenu itemWhatever;
and do:
itemWhatever.submenu = &function (X);
Can I call functionX doing:
(*itemWhatever.submenu)();
I did something similar to this and the compiler give this answer:
error: (183) function or function pointer required
Yes you can, but not quite the way you've written it.
A function pointer is not declared in quite the same way as a 'normal' pointer.
What you need is:
struct SitemMenu {
unsigned int id;
char * text;
void (* submenu)(void); // this is a function pointer, as opposed to the 'normal' pointer above
};
typedef struct SitemMenu TitemMenu;
TitemMenu itemWhatever;
then, if you have some function declared with the same parameters and return type, like:
void functionX(), then you can do:
itemWhatever.submenu = functionX;
itemWhatever.submenu();

function prototype with void* parameter

I have two functions, each taking a pointer to a different type:
void processA(A *);
void processB(B *);
Is there a function pointer type that would be able to hold a pointer to either function without casting?
I tried to use
typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};
but it didn't work (compiler complains about incompatible pointer initialization).
Edit: Another part of code would iterate through the entries of Ps, without knowing the types. This code would be passing a char* as a parameter. Like this:
Ps[i](data_pointers[j]);
Edit: Thanks everyone. In the end, I will probably use something like this:
void processA(void*);
void processB(void*);
typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};
...
void processA(void *arg)
{
A *data = arg;
...
}
If you typedef void (*processor_t)(); then this will compile in C. This is because an empty argument list leaves the number and types of arguments to a function unspecified, so this typedef just defines a type which is "pointer to function returning void, taking an unspecified number of arguments of unspecified type."
Edit: Incidentally, you don't need the ampersands in front of the function names in the initializer list. In C, a function name in that context decays to a pointer to the function.
It works if you cast them
processor_t Ps[] = {(processor_t)processA, (processor_t)processB};
By the way, if your code is ridden with this type of things and switch's all over the place to figure out which function you need to call, you might want to take a look at object oriented programming. I personally don't like it much (especially C++...), but it does make a good job removing this kind of code with virtual inheritance.
This can be done without casts by using a union:
typedef struct A A;
typedef struct B B;
void processA(A *);
void processB(B *);
typedef union { void (*A)(A *); void (*B)(B *); } U;
U Ps[] = { {.A = processA}, {.B = processB} };
int main(void)
{
Ps[0].A(0); // 0 used for example; normally you would supply a pointer to an A.
Ps[1].B(0); // 0 used for example; normally you would supply a pointer to a B.
return 0;
}
You must call the function using the correct member name; this method only allows you to store one pointer or the other in each array element, not to perform weird function aliasing.
Another alternative is to use proxy functions that do have the type needed when calling with a parameter that is a pointer to char and that call the actual function with its proper type:
typedef struct A A;
typedef struct B B;
void processA(A *);
void processB(B *);
typedef void (*processor_t)();
void processAproxy(char *A) { processA(A); }
void processBproxy(char *B) { processB(B); }
processor_t Ps[] = { processAproxy, processBproxy };
int main(void)
{
char *a = (char *) address of some A object;
char *b = (char *) address of some B object;
Ps[0](a);
Ps[1](b);
return 0;
}
I used char * above since you stated you are using it, but I would generally prefer void *.

typedef function return value in C

Please help me understand what this typedef is doing??
typedef void (xyz) (void *data);
extern struct x* FUNCTION(xyz *ptr);
Here is my understanding: in 1st line xyz is a function returning void and taking void pointer as an argument. But I cant interpret 2nd line with this understanding.
Any input is appreciable.
There is an external function called FUNCTION which takes a pointer to an xyz function as parameter and returns a pointer to a struct x.
The first line defines xyz to be the type of a function returning void and taking one argument of type void*. You can actually omit the name data, as it does nothing.
Since there are no raw function types in C that you can declare directly, you can only use pointers to xyz, as indeed you have xyz * ptr.
It is more common to include the pointer in the typedef:
typedef void (*fptr)(void*);
void call(fptr f, void * arg) { f(arg); }
void some_function(void * data); // whatever
int main()
{
void * p = malloc(8);
call(some_function, p);
}
The second line declares a function that takes an xyz* as an argument and returns a pointer to a struct x, with external linkage.

Passing a struct into a generic function in C

I declare a new struct with the name of "Struct"
I have a generic function that takes in an argument "void *data".
void Foo(void *data)
I pass an instance of "Struct" into the generic function.
Struct s;
Foo(&s);
I want to access one of the properties of the struct in the function.
void Foo(void *data) {
char *word = (char*) data.word;
}
It's not allowed because it doesn't recognize data as a valid struct.
I even try to declare the data as the struct type first, and I get an error.
void Foo(void *data) {
Struct s = (Struct) data;
char *word = s.word;
}
I get "conversion to non-scalar type requested".
First of all, you should turn on your compiler's warning flags (all of them). Then you should pass a pointer to your Struct and use something other than struct as a variable name:
Struct s;
Foo(&s);
Then, in Foo:
void Foo(void *data) {
Struct *s = data;
char *word = s->word;
}
You can't convert non-pointer types to and from void* like you're trying to, converting pointer types to and from void* is, on the other hand, valid.
You need to pass a pointer to you struct and get a pointer to the struct inside the function:
Struct struct;
Foo(&struct);
void Foo(void *data) {
Struct* struct = (Struct*) data;
char *word = struct->word;
}
You have to use -> operator when requesting structure member via pointer.
This should work: char *word = (char*) data->word;
You also have to pass the address of the structure to the function. Like this: Foo(&struct);.
Firstly you need to call the function correctly:
Struct s;
Foo(&s);
Notice you're now passing a pointer to the structure.
Now, the function has to know that you're using a Struct (as opposed to something else) - perhaps because of another parameter, or a global variable, or some other reason. Then inside the function you can do:
void Foo(void *data) {
Struct *structpointer = p; /* Note - no need for a cast here */
/* (determine whether data does refer to a pointer then...) */
char *word = structpointer->word;
/* ... then use 'word'... */
}
Data is pointer, so whatever you cast it to must also be a pointer. If you said Struct* myStruct = (Struct*) data, all would be well with the world.
You are mixing pointers and data.
Struct struct defines a data object
void *data expects data to be a pointer.
Call Foo with a pointer to a Struct, and make other necessary changes
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
Struct *struct = (Struct*)data;
char *word = struct->word;
}
or the more compact form:
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
char *word = ((Struct*)data)->word;
}

Resources