i'm having troubles trying to deference a void pointer in C.
Well, i make a linked list that have a "Nodo" with a void* info, that's because info will change of type.
typedef struct nodo
{
void *info; //This'll change types, like different structs.
char label; // S si es un switch, E si es un enemigo
struct nodo *siguiente;
}tNodo;
typedef struct Lista {
tNodo *head;
tNodo *tail;
tNodo *curr;
unsigned int listSize;
unsigned int pos;
}tLista;
Here's my struct tEnemigo, this'll be one of the struct that info could take.
typedef struct
{
char(*siguiente_movimiento)(void *,char **,int,int);
char tipo;
int maxmov;
int pasos;
char direccion;
int y;
int x;
}tEnemigo;
In this function i just pass void *general to take the info of it
char movEnemigos(tLista *listaEnemigos, char **map)
{
void *general;
general = &listaEnemigos->curr->info; //A struct
siguiente_movimiento(general, map , x, y);
}
And here's my problem, i can't give the "info" that is located general, i read something about cast the void pointer, but i failed miserably.
char siguiente_movimiento(void *general, char **map, int x, int y)
{
tEnemigo *enemigo;
enemigo = *(tEnemigo *) general ;
}
I don't know how to do this, maybe i'm wrong with all my "idea" of the code...hope you guys can give me a hand.
EDIT: THIS IS THE ERROR CODE.
error: incompatible types when assigning to type ‘tEnemigo’ from type ‘struct tEnemigo *’
*(tEnemigo *) general = enemigo;
In your siguiente_movimiento function, enemigo is a pointer, but you are trying to assign a value to it that is not a pointer (because you dereference it with *). Your function should look like this:
char siguiente_movimiento(void *general, char **map, int x, int y)
{
tEnemigo enemigo;
enemigo = *(tEnemigo *) general ;
}
Or:
char siguiente_movimiento(void *general, char **map, int x, int y)
{
tEnemigo *enemigo;
enemigo = (tEnemigo *) general ;
}
You currently have a mix of the two.
The error message gives the game away — you haven't declared a type struct tEnemigo.
You have:
typedef struct
{
...
}tEnemigo;
You either need to drop the struct when using the type, or you need:
typedef struct tEnemigo
{
...
} tEnemigo;
Both techniques work. I'd probably add the tag anyway, but I'd definitely write the code in terms of the typedef name (just tEnemigo), not struct tEnemigo.
And, as a side note, you should aim to avoid void * arguments. One advantage of the struct tEnemigo tag is that you can define opaque types by simply saying:
struct tEnemigo; // There is a type struct tEnemigo...
char siguiente_movimiento(struct tEnemigo *enemigo, char **map, int x, int y);
Your code that uses struct tEnemigo pointers does not need to know about the internals of the structure; only code that needs to look inside the structure needs to know the full type definition.
One reason for avoiding void * arguments is that any pointer type can be passed to a function that expects a void *. For example, if you have a FILE *fp = fopen("something", "r);, then the compiler cannot diagnose an error in:
char c = siguiente_movimiento(fp, map, 1, 3);
even though it is clearly a mistake. With the struct tEnemigo * declaration for the function, this mistake becomes a compilation error.
Rule of Thumb: if the void * argument only maps to a single type, then the chances are good that the function shouldn't be written with a void * argument. (There are exceptions: for example, if you have a family of functions called by function pointer, you might need a void * argument so that a single call can call any of the functions. Memory allocation functions are another special case.)
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:)
I have a array structure that should hold a pointer to another structure. My structures are like this:
struct Term{
char* term;
int times;
};
typedef struct Term TERM;
struct HeapTer{
TERM* Term;
size_t used;
size_t size;
};
typedef struct HeapTer HEAPTER;
struct Pack{
HEAPCON* hCon;
HEAPTER* hTer;
};
typedef struct Pack PACK;
Pack will just hold the pointers of both arrays I will return from my structure loading function.
My problem is when I will call a function, where I will insert a given term to the consults term heap.
InsertHeapTer(pack->hTer->Term[ind_term],consult->hTer)
Where InsertHeapTer is defined as InsertHeapTer(TERM* Ter, HEAPTER *t).
The compiler gives me the following error, error: incompatible types when assigning to type 'TERM {aka struct Term}' from type 'TERM * {aka struct Term *}'.
So, it is saying that when I use pack->hTer->Term[ind_term] it gives me a TERMand not a TERM*, even though it is defined as a pointer in the structure.
What am I doing wrong and why is this happening?
EDIT:
Code to reproduce:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Termo{
char* termo;
int vezes;
};
typedef struct Termo TERMO;
struct HeapTer{
TERMO* Termo;
size_t usado;
size_t tam;
};
typedef struct HeapTer HEAPTER;
struct consulta{
char *Local;
HEAPTER *hTer;
};
typedef struct consulta CONSULTA;
struct HeapCon{
CONSULTA* con;
size_t usado;
size_t tam;
};
typedef struct HeapCon HEAPCON;
struct Pacote{
HEAPCON* hCon;
HEAPTER* hTer;
};
typedef struct Pacote PACOTE;
void InsereHeapTer(TERMO* Ter, HEAPTER *t){
}
int main(){
PACOTE* pack;
CONSULTA* consulta;
int ind_termo=1;
InsereHeapTer(pack->hTer->Termo[ind_termo],consulta->hTer);
return 0;
}
void InsereHeapTer(TERMO* Ter, HEAPTER *t){
}
I'm sorry, but this was the minimal setup I could do.
So, it is saying that when I use pack->hTer->Term[ind_term] it gives
me a TERM and not a TERM*,
Yes.
even though it is defined as a pointer in
the structure.
Be careful: even though what is defined as a pointer? It is pack->hTer->Term that is so defined. With that being the case, then, pack->hTer->Term[ind_term] indeed has type TERM. It is equivalent to *(pack->hTer->Term + ind_term).
And that suggests a resolution: if you meant to pass a pointer to that item instead of a copy of the item, then you can use pointer arithmetic to produce the wanted pointer as pack->hTer->Term + ind_term. I tend to prefer the simplicity of that, but stylistically, I'm sure some people would prefer the equivalent expression &pack->hTer->Term[ind_term].
To simplify the offending line of code, you can do:
TERMO* termo = pack->hTer->Termo;
InsereHeapTer(termo[ind_termo],consulta->hTer);
Clearly, termo is a TERMO*. The [] operator is defined like this:
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).
C.11 §6.5.2.1 ¶2
Thus, your function call is equivalent to:
InsereHeapTer(*(termo + ind_termo),consulta->hTer);
And this can be simplified again:
TERMO* termo_plus_ind = termo + ind_termo;
InsereHeapTer(*termo_plus_ind,consulta->hTer);
When you dereference a TERMO*, you get a TERMO.
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 struct tnode { ... } Treenode;
Since typedef can't create a new type for us, is this part of the declaration of "struct tnode"? So in the above, is it creating a typedef "Treenode" AND declaring "struct tnode"?
return (Treeptr) malloc(sizeof(Treenode));
Here, since Treenode is a synonym for the entire "struct tnode" declaration, is it necessary to pass the whole declaration to sizeof or can one just do: sizeof(struct tnode) after declaring tnode elsewhere via struct tnode { ... };
typedef struct tnode *Treeptr;
Typedef is: typedef old-existing-type newtype; So here.. struct tnode * is the old type which must already exist (must be declared elsewhere) and Treeptr is the synonym for that.. but why can't we space the thing?? Like so: typedef struct tnode * Treeptr;
typedef int (*PFI)(char *, char *);
What is going on here? the old-type is int and (*PFI)(char , char) is a synonym for int?? If int (*PFI)(char *, char *) is the old-type, what's the new-type?? What does he mean by saying "In effect typedef is like #define, except that since it's interpreted by the compiler, it can cope with textual substitutions that are beyond the capabilities of the preprocessor"? In the mentioned example.. why can't the preprocessor do whatever is being done??
So in the above, is it creating a typedef "Treenode" AND declaring
"struct tnode"?
Yes, there are both declaration and typedef in the same sentence.
but why can't we space the thing?? Like so: typedef struct tnode *
Treeptr
If you are talking about the * - you can. it is a separate token anyway.
typedef int (*PFI)(char *, char *);
This is a function type definition;
typedef int (*PFI)(char *, char *);
^ define a type called
^PFI as:
^ pointer
^to function
^that receives two char pointers as arguments
^ and returns an int
Now you can use PFI instead of int (*)(char *, char *) (when used as a parameter / variable)
EDIT:
Code sample for using function pointer:
#include <stdio.h>
int add(int a, int b) { return a + b; }
typedef int (*pfi)(int,int);
int main()
{
pfi my_func = add;
int res;
res = (*my_func)(1,2);
printf( "add(1,2)=%d", res);
return res;
}