I have two or more linked lists that have the same names for their "next". For example,
struct server_t {
sockaddr_in * sin;
server_t * next_;
}
struct player_t {
char name[10];
player_t * next_;
}
How can I get a function to take in either type and manipulate the pointers?
I tried something like this:
static void add_entity( void * list, void * new) {
new->next_ = list;
list = new;
}
I thought that maybe I should cast add_entity() using a function pointer:
typedef void (*player_handler_t)(player_t * list, player_t * target);
typedef void (*server_handler_t)(server_t * list, server_t * target);
I was wondering what the most optimal method is?
IF I understand - one uses void * as the datatype in function arguments so that it can be cast to a fixed (read: one) datatype in the function.
If you choose to use anonymous blocks in the function, then you could use if() or switch() to select a datatype depending on another variable.
The best choice is to stick with a single datatype. If you need something "cool" use function pointers to branch to the right choice for the datatype you want:
The Function Pointer Tutorials - Syntax
technically you cannot do deferencing on void pointer,
its better to add one more argument to function which is either a enum or integer, which could be used to identify the data type.
Best Regards,
Rakesh UV
You could go the way you're going with function pointers, but you may want to make the function prototype take two void * as arguments. While it isn't exactly type safe, it does allow you to call the function pointer without warnings regarding the types passed. If you don't do this, all your callers will need to know which of the two functions they are calling to pass the correct type safe parameters.
so something like:
struct server_t
{
sockaddr_in * sin;
server_t * next_;
}
struct player_t
{
char name[10];
player_t * next_;
}
typedef void (*add_entity_t)(void **list, void * target);
static void add_server_entity(void **_list, void *_new)
{
#define list ((struct server_t *) _list)
#define new ((struct server_t *) _new)
new->next_ = *list;
*list = new;
#undef list
#undef new
}
static void add_player_entity(void **_list, void *_new)
{
#define list ((struct player_t *) _list)
#define new ((struct player_t *) _new)
new->next_ = *list;
*list = new;
#undef list
#undef new
}
int main(int argc, char **argv)
{
add_entity_t entityFn;
....
entityFn = add_server_entity;
entityFn(&serverHead, newServer);
}
I fixed the "list" argument, which needs to be a pointer to pointer since you are changing its value and the caller needs to see the new value for everything to work.
However, to be honest, I think all this is just a "waste" of time. You should concentrate on making a list package that is generic. Like, add_entity just takes a list and a void * for the data. It allocates nodes appropriately and you allocate the data you want to add to the list outside and pass it to an "add to list" function. The list entity just stores the next/prev pointers and a void * for the data item. In C++ you could use templates, in C you have to sacrifice type safety for the generic data item.