4

My code is below. On the lines marked with *'s, I get:

error: expected expression before ‘{’ token
rval.adj_list[0] = { {"B","C",3},{"B","A",2} };

Is there a compact way to initialize a dynamically allocated "double array" of pointers to pointers?

struct node;

struct edge {
    char *from;
    char *to;
    int weight;
};

struct digraph {
    char **vertices;
    struct edge **adj_list;
};

int main( int argc, char *argv[] ) {
    struct digraph rval;
    int size = 5;
    rval.vertices = malloc( size * sizeof(char*));
    rval.adj_list = malloc( size * sizeof(struct edge*));
    rval.vertices[0] = "A";
    rval.adj_list[0] = { {"A","B",2},{"A","E",1} };  //********
    rval.vertices[1] = "B";
    rval.adj_list[1] = { {"B","C",3},{"B","A",2} };  //********
    rval.vertices[2] = "C";
    rval.vertices[3] = "D";
    rval.vertices[4] = "E";
}
2
  • What's rval.vertices = malloc( size * sizeof(char*));? char* here is just a pointer, not the length you need. Commented Jan 31, 2014 at 0:34
  • char * is a pointer, not an array. arrays can be initialized with = {data}; , but not assigned. You're attempting to assign = {data} to a pointer, which is violates both of those. Commented Jan 31, 2014 at 0:42

2 Answers 2

4

You'd need a C99 'compound literal', which looks like a cast followed by an initializer in braces.

rval.adj_list[0] = (struct edge []){ {"A","B",2},{"A","E",1} }; 

This leads to:

#include <stdlib.h>

struct node;

struct edge {
    char *from;
    char *to;
    int weight;
};

struct digraph {
    char **vertices;
    struct edge **adj_list;
};

int main(void)
{
    struct digraph rval;
    int size = 5;
    rval.vertices = malloc( size * sizeof(char*));
    rval.adj_list = malloc( size * sizeof(struct edge*));
    rval.vertices[0] = "A";
    rval.adj_list[0] = (struct edge[]){ {"A","B",2}, {"A","E",1} };
    rval.vertices[1] = "B";
    rval.adj_list[1] = (struct edge[]){ {"B","C",3}, {"B","A",2} };
    rval.vertices[2] = "C";
    rval.vertices[3] = "D";
    rval.vertices[4] = "E";
}
Sign up to request clarification or add additional context in comments.

3 Comments

+1 I wish I could up vote this again. This comes up more often than people admit, and usually those that don't know how to do it often hack up middle-man solutions.
One thing eludes me. Both the types in the compound literal and the structure definition should be const, shouldn't they ? I would think it mattered (and I always do them that way) but i noticed they aren't here. Just curious.
If you can work out the correct mix of const qualifiers, be my guest to take the answer over. It isn't trivial to add them. The adjlist element itself must be writable; the array it points to, and the items that each element in the array point to, are not modifiable, strictly.
2

You could only initialize a whole structure in C99 mode preceding it by (struct edge[]). Otherwise you will have to initialize each member by itself:

rval.adj_list[0] = (struct edge[]){ {"A","B",2}, {"A","E",1} };
...
rval.adj_list[1] = (struct edge[]){ {"B","C",3}, {"B","A",2} };

Or:

rval.vertices[0] = "A";
rval.adj_list[0][0].from = "A";
rval.adj_list[0][0].to = "B";
rval.adj_list[0][0].weight = 2;
rval.adj_list[0][1].from = "A";
rval.adj_list[0][1].to = "E";
rval.adj_list[0][1].weight = 1;
rval.vertices[1] = "B";
rval.adj_list[1][0].from = "B";
rval.adj_list[1][0].to = "C";
rval.adj_list[1][0].weight = 3;
rval.adj_list[1][1].from = "B";
rval.adj_list[1][1].to = "A";
rval.adj_list[1][1].weight = 2;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.