Reputation: 275
I apologize if this might be viewed as a duplicate, but I cannot seem to find a conclusive answer that satisfies my question. So I have a struct with a self referential pointer to pointers.
struct Node {
int id;
int edge_count;
struct Node **edges;
}
static struct Node s_graph[MAX_ID+1];
I then have a function that allocates some memory.
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;
}
The above seems to work just fine. However, I keep seeing posts about pointer to pointers that lead me to wonder if I need to do something like the following in add_edge:
struct Node *phead = malloc(sizeof(struct Node *));
However, this does not seem logical. There should be enough memory for ptail->edges to store this pointer after the realloc call. I am fairly confident that I did the allocation correctly (albeit, inefficiently), but it is kind of sending me on a mind trip ... So when people declare pointer to pointers (e.g., **ptr) and then allocate memory for both ptr and *ptr, wouldn't that technically make ptr a pointer to pointers to pointers (and maybe clearer to declare as ***ptr)? Or maybe I am wrong and missing something conceptually?
Thank you in advance!
Upvotes: 0
Views: 70
Reputation: 133557
It depends on the situation, there is no general answer. If you have a pointer to pointer, eg Node**
, and you want to store new data into it, then you need to have two levels of allocations, otherwise one is enough.
struct Node** nodes = calloc(AMOUNT, sizeof(struct Node*));
Now you have an array of struct Node*
elements, so each element is a pointer to a struct Node
.
Now how do you fill this array? You could want to insert new nodes inside it. Then you wouold require to allocate them, eg
nodes[0] = calloc(1, sizeof(struct Node)); // <- mind Node, not Node*
But in your situation you just want to set the address to an element of an array of the static variable s_graph
, so you don't need to allocate a second level, you directly set the value.
So:
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 |
But if you have s_graph
you already have them allocated, so it's something like:
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 |
Upvotes: 2