Arkleseisure
Arkleseisure

Reputation: 438

How do I initialize an array of pointers to structures in C?

I am attempting to create an array of pointers to structs. I would like each of the structs to have the same values on initialization, but not the same pointers to them.

Currently I am attempting to do it like this:

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

struct Node {
    float value;
    bool evaluated;
    struct Node* children[10];
};

void main() {
    int i;

    struct Node* node = &(struct Node) {
        .value = 0,
        .evaluated = false,
        .children = { 0 }
    };

    for (i = 0; i < 10; i++) {
        node->children[i] = &(struct Node) {
            .value = 0,
            .evaluated = false,
            .children = { 0 }
        };
        printf("Index: %d, pointer: %p\n", i, node->children[i]);
    }
}

Unfortunately, this gives me these results:

Index: 0, pointer: 00DEF640
Index: 1, pointer: 00DEF640
Index: 2, pointer: 00DEF640
Index: 3, pointer: 00DEF640
Index: 4, pointer: 00DEF640
Index: 5, pointer: 00DEF640
Index: 6, pointer: 00DEF640
Index: 7, pointer: 00DEF640
Index: 8, pointer: 00DEF640
Index: 9, pointer: 00DEF640

Is there any way I could produce this in such a way as to give the same results, but with different pointers to each of the structs?

Upvotes: 1

Views: 624

Answers (3)

Fe2O3
Fe2O3

Reputation: 8364

Why do you want to use pointers?

struct Node {
    float value;
    bool evaluated;
    struct {
        float value;
        bool evaluated;
     } child[10];
 } node;

Initialising may be as simple as memset( &node, 0, sizeof( node ) );

Then you can use node.value for the top level, and node.child[i].value for any of the 10 "children".

Use printf( "%d %p\n", i, &node.child[i] ); to confirm that you have 10 distinct 'sub-nodes'.

Do you want each of the 10 "children" to have 10 (unused?) pointers (to grandchildren)?

Upvotes: 1

Barmar
Barmar

Reputation: 782785

When you use a compound literal, the lifetime of the object is the containing block. When you do this in a loop, the lifetime of each array element ends when the loop iteration completes. So these pointers become invalid.

You need to use dynamic allocation with malloc() to create multiple array elements. You can then copy into the allocated memory by assigning from the compound literal.

There's no need to use a compound literal for the top-level node, you can just use an ordinary local variable there.

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

struct Node {
    float value;
    bool evaluated;
    struct Node* children[10];
};

void main() {
    int i;

    struct Node node = {
        .value = 0,
        .evaluated = false,
        .children = { 0 }
    };

    for (i = 0; i < 10; i++) {
        node.children[i] = malloc(sizeof *node.children[i]);
        *(node->children[i]) = (struct Node) {
            .value = 0,
            .evaluated = false,
            .children = { 0 }
        };
        printf("Index: %d, pointer: %p\n", i, node->children[i]);
    }
}

Upvotes: 2

dbush
dbush

Reputation: 225817

A compound literal has a lifetime of the block it is declared in. So after each iteration of the for loop the literal no longer exists and therefore the pointer to it is invalid, and using such a pointer triggers undefined behavior

Rather than using compound literals, you should allocate memory dynamically for each instance. And since you're initializing the members with all zero values, you can use calloc to return zero-initialized memory.

struct Node* node = calloc(1, sizeof(struct Node));

for (i = 0; i < 10; i++) {
    node->children[i] = calloc(1, sizeof(struct Node));
    printf("Index: %d, pointer: %p\n", i, node->children[i]);
}

Upvotes: 3

Related Questions