C关于指针内存分配指针的困惑?

时间:2015-11-20 00:08:08

标签: c pointers memory-management

如果这可能被视为重复,我道歉,但我似乎无法找到满足我的问题的结论性答案。 所以我有一个带有指向指针的自引用指针的结构。

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-gt; edge存储该指针。我相当确信我正确地进行了分配(尽管效率低下),但它有点让我精神错乱......所以当人们声明指针指针(例如** ptr)然后为两者分配内存时ptr和* ptr,技术上不会让ptr成为指向指针的指针(并且可能更清楚地声明为*** ptr)?或许我错了,在概念上遗漏了什么?

提前谢谢!

1 个答案:

答案 0 :(得分:2)

这取决于具体情况,没有一般答案。如果你有一个指向指针的指针,例如Node**,并且你想将新数据存储到指针中,那么你需要有两个级别的分配,否则就足够了。

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

现在您有一个struct Node*元素数组,因此每个元素都是指向struct Node的指针。

现在你如何填补这个阵列?您可能希望在其中插入新节点。然后你需要分配它们,例如

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      |