2017-06-27 42 views
1

我們都給出了任務和鏈表的結構:鏈表 - 單或雙指針頭

typedef struct dlistint_s 
{ 
    int n; 
    struct dlistint_s *prev; 
    struct dlistint_s *next; 
} dlistint_t; 

並與原型如下功能:

dlistint_t *add_dnodeint(dlistint_t **head, const int n); 

什麼優點以及爲什麼在創建函數時會使用雙指針指向頭部?

+0

我會建議不要這種設計。最好有一個「list」結構,指向第一個和最後一個「節點」。這可以讓你通過傳遞它來修改列表,而不是直接使用節點 – Alexander

+0

通常,你可以使用'bool add_dnodeint(dlistint_t ** head,int n)'和一個指向參數的指針和一個非指針返回值(或無返回值 - 'void'),或'dlistint_t * add_nodeint(dlistint_t * head,int n)'帶有一個簡單的指針參數和一個匹配的指針返回值(用作head = add_nodeint(head,newval) ;')。您通常不會同時執行這兩個操作 - 使用指向參數的指針並返回指針值。請注意,'const int n'幾乎沒有意義,因爲'n'不是一個指針。 –

回答

6

將指針傳遞到指針head的原因是指針head的任何修改都會在調用者函數中看到,並且您不必從函數返回頭部。

例如,考慮這個簡單的節點:

struct Node{ 
    int data; 
    struct Node *next; 
}; 

的一種功能節點在前面

struct Node *add_node (struct Node *list, int n){ 
    struct Node *new_node = malloc(sizeof(struct Node)); 
    if(new_node == NULL){ 
     printf("Memory allocation failed\n"); 
     exit(EXIT_FAILURE); 
    } 
    new_node->data = n; 
    new_node->next = list; 
    return new_node; 
} 

添加到列表中。如果我們需要分配new_nodelist,而不是返回的那麼我們需要修改上面的函數,並刪除return語句併發出聲明

list = new_node; 

但是,,這將無法正常工作!
這是因爲在C中,像所有參數一樣,指針是按值傳遞的。 這意味着list包含傳遞給add_node函數的指針值的副本,而不是傳遞給此函數本身的指針。
這就是我們需要指針指針的地方。

void add_node (struct Node **list, int n){ 
    struct Node *new_node = malloc(sizeof(struct Node)); 
    if(new_node == NULL){ 
     printf("Memory allocation failed\n"); 
     exit(EXIT_FAILURE); 
    } 
    new_node->data = n; 
    new_node->next = *list; 
    *list = new_node; 
} 
0

因爲如果你使用的是dlistint_t *head變量,而不是在函數參數使用dlistint_t **head變量然後在變量head在功能dlistint_t *add_dnodeint(dlistint_t **head, const int n);所做的更改將是本地的這種方法。由於您使用的是Node*,所以在變量head中完成的更改對於該功能而言是本地的。如果你想反映這些變化,即使在函數調用後(你顯然想要),然後使用dlistint_t **head

2

如果您使用雙指針,您可以傳遞頭部的地址,以便您的函數可以修改實際的指針。這樣你就不需要返回新的頭部。