我正在尝试实现链表的insert-at-head功能,并希望通过引用传递返回到新插入节点的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
不会更改其先前的值。任何建议或帮助表示赞赏,谢谢!
答案 0 :(得分:1)
嗯,我知道您无法更改参数,但如果您可以更改此功能的实现和调用者,则可以进行操作!
关于C的可怕(很好)的事情是你可以把任何东西投射到任何你想要的东西上。因此,即使您无法更改功能签名以获取无效**,您仍然可以通过一个。例如:
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;
}
瞧!顺便说一句,这对于来电者来说是可怕的并且不直观。我希望这不是生产代码:)
答案 1 :(得分:0)
如前所述,如果你不能修改函数原型,你仍然可以使用你的void*
参数将任何类型的指针传递给函数,包括指向指针以返回你的新元素。 / p>
让我只改进代码,以显示此用法的抽象示例:
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;
}