2

I have a struct which is a node, and another which is a list of these nodes. In the list struct, its an array of nodes, but instead of an array, it's a pointer to pointer with a size integer:

typedef struct node {
    struct node *next;
    MyDef *entry;
} Node;


typedef struct list {
    Node **table;
    int size;
} List;

List *initialize(void)
{
    List *l;
    Node **n;

    if ((l = (List *)malloc(sizeof(List))) == NULL)
        return NULL;
    l->size = 11;

    /* I think this is correctly allocating the memory for this 'array' of nodes */
    if ((n = (Node **)malloc(l->size * sizeof(Node))) == NULL)
        return NULL;

    /* Now, how do I set MyDef *entry and Node *next to NULL for each of the 'array'? */

    l->table = n;

    return l;
}

How do I set MyDef *entry and Node *next to NULL for each of the 'array'?

2
  • too many stars ... you use ** for "2D arrays", not for a list of 'simple' elements Commented Oct 26, 2010 at 9:56
  • Taken from here: eternallyconfuzzled.com/tuts/datastructures/… Commented Oct 26, 2010 at 10:01

2 Answers 2

1

(Node **) is pointer to [array of] pointer to Node, so array you allocate will not have any struct members.

You should use (Node *) and then you'll have pointed array of Node structs, or allocate each Node separately, then place pointers to them into your array.

There's exist function calloc() in standard C library for your case: it inits allocated area with 0's (which corresponds to (char/short/int/long)0, 0.0 and NULL).

Also there's a memory leak.

/* I think this is correctly allocating the memory for this 'array' of nodes */
if (... == NULL)
    return NULL;

When array allocation fails you do not free List, but lose pointer to it. Rewrite it as:

/* I think this is correctly allocating the memory for this 'array' of nodes */
if ((n = (Node **)malloc(l->size * sizeof(Node))) == NULL) {
    free(l);
    return NULL;
}

So from my point of wiev correct code would be:

typedef struct node {
    struct node *next;
    MyDef *entry;
} Node;


typedef struct list {
    Node *table; /* (!) single asterisk */
    int size;
} List;

List *initialize(void)
{
    List *l;
    Node **n;

    if ((l = (MList *)malloc(sizeof(List))) == NULL)
        return NULL;
    l->size = 11;

    /* I think this is correctly allocating the memory for this 'array' of nodes */
    if ((n = (Node *)calloc(l->size, sizeof(Node))) == NULL)
    {
        free(l);
        return NULL;
    }

    /* Now, how do I set MyDef *entry and Node *next to NULL for each of the 'array'? */

    l->table = n;

    return l;
}

Futhermore C99 allows you to make variable size structs, so you able to init struct like

typedef struct list {
    int size;
    Node table[0]
} List;

And allocate as many Node's in table as you want using malloc(sizeof(List) + sizeof(Node)*n);

Sign up to request clarification or add additional context in comments.

12 Comments

Thank you ever so much for taking the time to do this. I'm trying this out as I type this.
Just tried this, although this bit works great, I really do think I need the Node**. Reason is, in another bit of the program, I do "n->next = (*l)->table[int val];", where int val is < l->size. This doesnt work without the ** as its not an array?
n->next is a pointer to Node, (l)->table[val] is a Node, so you have to get pointer to it. Write &((l)->table[val]) or shorter (l)->table+val (table+val gives you pointer to val-th element of table). Node** will actually denote array of pointer to Node's, so in this case you should also allocate space for every node and store pointer to it in array elements.
Thanks @Vovanium. Just one last error: should Node **n be Node *n? Otherwise VS 2010 doesnt like "n = (Node *)calloc...". Also VS 2010 is breaking on "l->table = n;"?
Oh, you're right, 'Node *n' is correct, i missed this when edited the source.
|
0

First of all, it seems to me that you have an error in your code allocating the array: It should say sizeof(Node*) rather than sizeof(Node) as you want to allocate an array of pointers to Node not an array of Node objects.

Then you can iterate through the array list:

for ( unsigned i = 0; i < l->size; ++i )
{
    Node* node = l->table[ i ];
    node->entry = NULL;
    node->next = NULL;
}

Another hint: You really should check your initialization function against possibilities of memory leaks.

5 Comments

Thanks, tried this and get an error:l->table CXX0030: Error: expression cannot be evaluated
Any idea why this isn't working? The VS 2010 debugger breaks on Node* node = l->table[i];
I forgot: The individual objects have to be created as well. But it seems not to be the problem in your case as the error already occurs in the line accessing the table. But, just to have it correct, there is need for something like l->table[i] = malloc(sizeof(Node)).
Thanks @Flinsch, I put that line in immediately before the Node* node = ... line and it still broke on the Node* node = ... line!
Did you try the debugger having a look at the values of l and l->table at that line immediately before the program crashes?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.