我试图实现一个链表的插入头部功能,并希望通过引用传递返回一个void*指针到新插入的节点。不幸的是,我不能改变参数。这是我的相关代码:
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;
}
我试图将element
设置为新插入节点的开始,但是当它返回时,element
不会改变其先前的值。任何建议或帮助是感激的,谢谢!
嗯,我知道你不能改变参数,但是如果你可以改变这个函数的实现和调用者,你可以做到这一点!
关于C的可怕(也不错)的事情是你可以将任何东西强制转换为你想要的任何东西。因此,即使你不能改变函数签名来接受void**,你仍然可以传递一个。例子:
char *element = (char *)malloc(0xDEADBEEF);
List_Insert(list, (void*)&element, key);
在函数内部,可以将其强制转换为void**:
void List_Insert(list_t *list, void *element, unsigned int key) {
void **e = (void **)element;
/* do stuff */
*e = (void *)list_new;
}
瞧!顺便说一句,这太可怕了,对调用者来说不直观。我希望这不是生产代码:)
正如已经建议的,如果你不能修改函数原型,你仍然可以使用你的void*
参数传递任何类型的指针到函数,包括指针对指针返回你的新元素。
让我对代码进行细化,以显示这种用法的不那么抽象的示例:
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;
}