C语言中通过引用传递参数的替代解决方案

时间:2014-03-29 02:51:49

标签: c pointers linked-list pass-by-reference

我正在尝试实现链表的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不会更改其先前的值。任何建议或帮助表示赞赏,谢谢!

2 个答案:

答案 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;
}