2015-11-20 79 views
0

我很抱歉,如果這可能被視爲重複,但我似乎無法找到一個結論性的答案,滿足我的問題。 所以我有一個指向指針的自引用指針的結構。C關於指向內存分配的指針的困惑?

struct Node { 
    int id; 
    int edge_count; 
    struct Node **edges; 
} 

static struct Node s_graph[MAX_ID+1]; 

然後我有一個函數,分配一些內存。

int add_edge(int tail, int head) 
{ 
    struct Node *ptail, *phead; 
    ptail = &s_graph[tail]; 
    phead = &s_graph[head]; 

    ptail->edges = realloc(ptail->edges, ++ptail->edge_count * sizeof(struct Node *)); 
    if (ptail->edges) { 
     *(ptail->edges + ptail->edge_count - 1) = phead; 
     return 0; 
    } 
    return -1; 
} 

以上似乎工作得很好。不過,我不斷看到有關帖子的指針的指針,導致我想知道如果我需要做類似的東西在的add_edge如下:

struct Node *phead = malloc(sizeof(struct Node *)); 

然而,這似乎並不符合邏輯。在realloc調用之後,ptail-> edge應該有足夠的內存來存儲這個指針。我相當確信我正確地執行了分配(儘管效率很低),但它讓我有一種心理上的感覺......所以當人們聲明指向指針的指針時(例如,** ptr),然後爲兩者分配內存ptr和* ptr,在技術上不會使ptr成爲指向指針指針的指針(也許更清晰地聲明爲*** ptr)?或者,也許我錯了,在概念上錯過了一些東西?

預先感謝您!

+1

你有什麼看起來確定我。除了在每個新節點上重新分配都有點低效。通常的做法是以大塊進行分配/增長。 「所以當人們聲明指向指針的指針(例如,** ptr),然後爲ptr和* ptr分配內存時,」。你也這樣做了。除了第二級('* ptr')不是動態內存,而是靜態內存。 – kaylum

回答

2

這要看情況,沒有一般的答案。如果你有一個指向指針的指針,例如Node**,並且你想存儲新的數據,那麼你需要有兩個級別的分配,否則就足夠了。

struct Node** nodes = calloc(AMOUNT, sizeof(struct Node*)); 

現在你有struct Node*元件的陣列,使每個元素是一個指向struct Node

現在你怎麼填這個數組?您可能想要在其中插入新節點。然後,你需要wouold分配它們,例如

nodes[0] = calloc(1, sizeof(struct Node)); // <- mind Node, not Node* 

但在你的情況,你只是想將地址設置爲靜態變量s_graph數組的元素,所以你並不需要分配一個第二級,你直接設置的值。

所以:

struct Node** nodes = calloc(AMOUNT, sizeof(struct Node*)); 

nodes -> | 0 | 1 | 2 | 3 | 

nodes[0] = calloc(1, sizeof(struct Node)) 

nodes -> | 0 | 1 | 2 | 3 | 
      | 
      | 
      v 
     | NODE | 

但如果你有s_graph你已經將其分配的,所以它是這樣的:

static struct Node s_graph[MAX_ID+1]; 
struct Node** nodes = calloc(AMOUNT, sizeof(struct Node*)); 

nodes -> | 0 | 1 | 2 | 3 | 
s_graph -> |  N1  |  N2  |  N3  | 

nodes[0] = &s_graph[0]; 

nodes -> | 0 | 1 | 2 | 3 | 
      | 
      |----| 
        v 
s_graph -> |  N1  |  N2  |  N3  |