Reputation: 269
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!
Upvotes: 1
Views: 116
Reputation: 971
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;
}
Upvotes: 0
Reputation: 148
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 :)
Upvotes: 1