I am passing data of type struct Person to a linked list, so each node's data pointer points to a struct Person.
struct Person {
char name[16];
char text[24];
};
I am trying to traverse the list and print the name/text in each node by calling
traverse(&list, &print);
Prototype for traverse is:
void traverseList(struct List *list, void (*f)(void *));
List is defined as:
struct List {
struct Node *head;
};
My print function accepts a void * data :
print(void *data) { .... }
I know I have to cast the data to struct Person, correct?
struct Person *person = (struct Person *)data;
printf("%s", person->name);
I know this is not sufficient since I am getting an "initialization from incompatible pointer type" warning. How can I successfully cast a void* in this case? Thank you.
The problem's not with the cast, or even with the way you're passing the function around. The problem is that your declaration of print is missing a return type, in which case int is usually assumed. The compiler is complaining because you're passing an int (*)(void*) to a function that's expecting a void (*)(void*).
It's easy to fix: simply add void in front of your print function declaration. See:
https://gist.github.com/ods94065/5178095
My print function accepts a void * data
I would say, rewrite your print function by accepting struct Person * .
Your traverseList function accepts a function pointer (which takes a void pointer), but it doesn't accept an argument for that void data. It seems that this is what you're after:
void print (void* data)
{
printf("%s", ((struct Person*)data)->name);
}
void traverseList (struct List *list, void(*f)(void*), void* data)
{
f(data);
}
Then you can call traverseList:
traverseList (&list, &print, &person);
Related
Hi I've been looking over stackoverflow and I'm really struggling with function pointers as parameters.
I have the structure:
struct Node {
struct Node *next;
short len;
char data[6];
};
and the functions:
void selectionsort(int (*compareData)(struct Node *, struct Node *), void (*swapData)(struct Node *, struct Node *), int n);
compare(struct Node *a, struct Node *b);
swap(struct Node *a, struct Node *b);
selection sort serves only to call compare and swap:
void selectionsort(int compare(struct Node *a, struct Node *b), void swap(struct Node *a, struct Node *b), int n){
int i;
for (i = 0; i < n; i++){
compare(a, b);
swap(a, b);
}
}
(the contents above may be incorrect, I have yet to get to fooling around with the actual selectionsort function really).
The problem arises when I call selectionsort in main. I was under the impression this would work:
int main(int argc, char **argv){
int n;
struct Node *list = NULL;
for (n = 1; n < argc; n++)
list = prepend(list, argv[n]); //separate function not given here.
int (*compareData)(struct Node *, struct Node *) = compare; //not sure I needed to redeclare this
void (*swapData)(struct Node *, struct Node *) = swap;
selectionsort(compareData(list, list->next), swapData(list, list->next), argc);
//other stuff
return 0;
}
Note: the function prepend contains the malloc for the struct, so that's been dealt with.
The problem I'm having is no matter how I play around with my function declarations etc, I always get the following error:
warning: passing argument 1 of 'selectionsort' makes pointer from integer without a cast [enabled by default]
note: expected 'int (*)(struct Node *, struct Node *)' but argument is of type 'int'.
Any help explaining why I'm getting this error message and how to fix it would be immensely appreciated.
I understand that the function is expecting a function pointer but I assumed my code above would allow for compareto be called. Any input would be greatly appreciated, also this is for an assignment (so please help me avoid cheating) and the parameters int(*compareData)(struct Node *, struct Node *) void (*swapData)(struct Node *, struct Node *) were given.
In
selectionsort(compareData(list, list->next), swapData(list, list->next), argc);
you are passing the result of calling the function compareData. This is wrong.
The same holds for swapData.
Just pass the function itself (resp. a pointer to it):
selectionsort(compareData, swapData, argc);
In your call to selectionsort you are actually calling those function pointers, causing you to pass the result of those calls to selectionsort. They are normal variables, and should be passed to selectionsort like any other variable argument.
However, you don't actually need the variables, you can just pass the functions directly:
selectionsort(&compare, &swap, argc);
Note that the address-of operator is not strictly needed, but I prefer to use them to explicitly tell the reader that we are passing pointers to those functions.
I'm trying to implement the insert-at-head functionality of a linked list, and would like to return a void* pointer to the newly inserted node via passing by reference. I unfortunately cannot change the parameters. This is my relevant code:
typedef struct List_t_def{
spinlock_t * lock_counter;
unsigned int key;
struct List_t_def *next;
}list_t;
typedef volatile unsigned int spinlock_t;//basic lock
void List_Insert(list_t *list, void *element, unsigned int key) {
list_t * list_new = (list_t *)malloc(sizeof(list_t));
spinlock_t * lock_temp = (spinlock_t*)malloc(sizeof(spinlock_t));
list_new->lock_counter = lock_temp;
spinlock_acquire(list->lock_counter);
list_new->key = key; //inserting the new created node as the first one (head of the linked list)
list_new->next = list->next;
list_new->lock_counter = list->lock_counter;
list->next = list_new;
element = (void*)list_new;
spinlock_release(list->lock_counter);
return;
}
I'm trying to set element to the start of the newly inserted node, but when it returns, element doesn't change its previous value. Any suggestions or help is appreciated, thanks!
Well, I know you can't change the parameters but if you can change the implementation and and the caller of this function you could do it!
The horrible(ly nice) thing about C is that you can cast anything to anything you want. So even though you can't change the function signature to take a void** you can still pass one anyway. Example:
char *element = (char *)malloc(0xDEADBEEF);
List_Insert(list, (void*)&element, key);
Inside the function, you can cast it back to a void**:
void List_Insert(list_t *list, void *element, unsigned int key) {
void **e = (void **)element;
/* do stuff */
*e = (void *)list_new;
}
Voila! BTW, this is horrible and not intuitive for the caller. I hope this is not production code :)
As already was suggested if you can't modify function prototype, you can still use your void* parameter to pass any kind of pointer into the function, including pointer-to-pointer to return your new element.
Let me just refine the code to show less abstract example for this usage:
void List_Insert_Caller() {
// ...
list_t *new_element;
List_Insert(list, &new_element, key);
// new_element now points to newly created list_t element
}
void List_Insert(list_t *list, void *new_element_ptr_ptr, unsigned int key) {
// ...
list_t **new_element = (list_t **)new_element_ptr_ptr;
// ...
*new_element = list_new;
}
I am writing a generic linked list implementation in pure C.
struct Node {
void *value;
struct Node *next;
};
struct LinkedList {
struct Node *start;
struct Node *end;
};
void LinkedList_new(struct LinkedList* llist) {
llist->start = 0;
llist->end = 0;
return;
}
void addNode( struct LinkedList *ll, void *_value ) {
if ( NULL == ll->start ) {
ll->start = (struct Node *) malloc( sizeof(struct Node) );
ll->end = ll->start;
} else {
ll->end->next = (struct Node *) malloc( sizeof(struct Node) );
ll->end = ll->end->next;
}
ll->end->value = _value;
return;
};
This all works great. My problem is when I get to printing value to the screen. I can't seem to find a generic implementation for printing.
Is there a way to determine the TYPE allocated to void *? (And then just do conversion using a switch statement)
void printFunc(int aInt) {
char str[15];
sprintf(str, "%d", aInt);
printf(str);
}
This is an implementation that works for int. Worst case I was thinking was writing a different function for each TYPE. Is this really my only route when using void *?
Is there a better way to do this?
No, there's no way to figure that out from the pointer alone. That would require type information to be stored at some well-defined location in all run-time structures, which is simply not how C uses the machine.
The common solution is for the user of the datatype to provide the print function that the application needs, since the application will know the type of data being stored. That is, there is usually an iteration function that takes a function pointer, calling the user's function (which might print the element) on each element of the list.
Here's how such a function could look:
void LinkedList_foreach(const LinkedList *start,
bool (*func)(void *element, void *data), void *data);
The above should call func() for each element of the list, passing it the element's data and the additional user-supplied data pointer which can be used by the caller to maintain state for the traversal. The callback func() should return false to stop the iteration, true to keep going.
To print an integer, assuming the integers are stored in the pointers, you could have:
static bool print_int(void *element, void *data)
{
printf("%d\n", (int) element);
return true;
}
Also, please don't cast the return value of malloc() in C.
I have a (hopefully) very simple issue that has been giving me problems for a while now. Given these structs
typedef struct
{
void * entity;
} link_t;
typedef struct
{
link_t * current;
} list_t;
and a function prototype
void *list_get_entity(list_t *list);
I need the function list_get_entity to return the address of the data that "entity" is pointing to. The best I've been able to do so far is
void *list_get_entity(list_t *list)
{
return list->current->entity;
}
which at least compiles and runs, but gives me gibberish. If for some reason the full file is needed to figure something out please let me know, although I'm sure there's other bugs in there I have yet to find because of this error.
Edit: fixed the code
To get the address of the data entity is pointing to just return it directly
return list->current->entity;
The void* is an address hence returning it directly by value will give the caller the address of the data
typedef struct
{
void * entity;
} link_t;
typedef struct
{
link_t * current;
} list_t;
void * list_get_entity(list_t *list)
{
return list->current->entity;
}
list->current is a pointer to link_t; list->current->entity is a pointer to entity type.
If you add &() around list->current->entity, it becomes pointer to pointer to void.
I am trying to create a linked list in C but trying to pack it nicely in somewhat of a C++ style class. I am having some issues however using function pointers in C.
typedef struct linkedList {
int count;
struct msgNode *front;
struct msgNode *back;
void (*addMSG)(unsigned char *, int, struct linkedList *);
} msgList;
void addMSG(unsigned char *data, int size, struct linkedList *self);
Ideally, I would like to have it such that you can make you list and then to add you can simply call a "method"(function) within the structure, simulating behavior you would see in C++.
Currently I get a segmentation fault when I call addMSG, which of-course is because addMSG is not pointing to a function. However, I don't want to have to specify a function to point to every single time I want use a linked list. Is there any nice way to have function pointers without implicitly having to point to the function, or do you have to implicitly point it to the function?
This is only the partial implementation shown here. At the end, this struct will have all the necessary functions. This is just for the sake of keeping this question short and to the point.
You need to assign the function to the member. i also recommend giving them different names:
typedef void (*addMSGFunc)(unsigned char *, int, struct linkedList *);
typedef struct linkedList {
int count;
struct msgNode *front;
struct msgNode *back;
addMSGFunc addMSG;
} msgList;
void addMSGImpl(unsigned char *data, int size, struct linkedList *self)
{
...
}
And then after creating a msgList:
msgList myList;
myList.addMSG = addMSGImpl;
Well you can't add a default value in the declaration of the struct but what you can do is:
Create a function to initialize the linkedList instance - I guess you've seen that in C style libraries
Create a default list item and use that when creating new entities.
Like:
void addMSG(unsigned char *data, int size, struct linkedList *self);
struct linkedList {
int count;
struct msgNode *front;
struct msgNode *back;
void (*addMSG)(unsigned char *, int, struct linkedList *);
} DefaultList = {0, NULL, NULL, addMSG};
You can have an uninitialized function pointer just fine as long as you don't actually use it. If you do want to use it to call a function, then obviously you have to assign a function to it. C is unable to guess which function you want to use.
If you have a linked list structure where sometimes you need a function, and sometimes you don't, then just assign NULL to it when you create the list, and have your list implementation only call the function when it's not NULL.
If it always points to the same function, then just do the assignment in your constructor function.