views:

1558

answers:

6
+5  Q: 

jagged array in c

Is there such a thing as a jagged array in C or C++?

When I compile this:

int jagged[][] = { {0,1}, {1,2,3} };

I get this error:

error: declaration of `jagged' as multidimensional array must have bounds for all dimensions except the first

+12  A: 

If you just want to initialise it, you can say:

int jagged[][3] = { {0,1}, {1,2,3} };

but the array will still have the shape [2][3]. If you want a true jagged array, you will have to create it dynamically. And if you do that, and are using C++, you should use a std::vector, as friol suggests.

anon
+8  A: 

In C++ (not compiled, and probably there's a more compact syntax):

std::vector<std::vector<int> > myArray;

myArray.push_back(std::vector<int>());
myArray.push_back(std::vector<int>());

myArray[0].push_back(0);
myArray[0].push_back(1);

myArray[1].push_back(1);
myArray[1].push_back(2);
myArray[1].push_back(3);

So now you can access the elements with, for example, myArray[0][0], etc.

friol
Erm you are pushing a pointer into a vector that doesn't hold pointers ...
Goz
Yes, you simply need to remove the "new"s - which is what I think was meant in the first place.
anon
i've applied the obvious fix.
Johannes Schaub - litb
you're right, thanks.
friol
+11  A: 

In C I would use an array of pointers.

For instance:

int *jagged[5];

jagged[0] = malloc(sizeof(int) * 10);
jagged[1] = malloc(sizeof(int) * 3);

etc etc.

Simon
+6  A: 

There's a bunch of ways to do it. Here's another way:

int jagged_row0[] = {0,1};
int jagged_row1[] = {1,2,3};
int *jagged[] = { jagged_row0, jagged_row1 };
rampion
+1. This is where C99's compound literals show off: `int *jagged[] = { (int[]){0,1}, (int[]){1, 2, 3} };` isn't that nice too?
Johannes Schaub - litb
The trouble with this solution is that the sub-arrays immediately decay to pointers, so you have no means of telling what the bounds are.
anon
@Neil, i didn't think of this at all. Of course you are right. Good point :)
Johannes Schaub - litb
@Neil: that's where guardian values come in handy to mark the end of the array
Christoph
@Christoph Guardian values can be problematic for arrays of numbers, as there may be no allowable "special" value. I think storing the array dimension explicitly somehow is better practice.
anon
@Neil Agreed on the subject of guardian values. Integers are overloaded enough as it is. Since I can't rely on the sizeof(array)/sizeof(*array) trick when passing arrays to functions, I always put array sizes in a size_t or something.
rampion
A: 

In C99 you can do the following:

int jagged_row0[] = {0,1};
int jagged_row1[] = {1,2,3};

int (*jagged[])[] = { &jagged_row0, &jagged_row1 }; // note the ampersand

// also since compound literals are lvalues ...
int (*jagged2[])[] = { &(int[]){0,1}, &(int[]){1,2,3} };

The only difference here (as compared to rampion's answer) is that the arrays don't decay to pointers and one has to access the individual arrays via another level of indirection - (e.g. *jagged[0] - and the size of each row has to be recorded - i.e. sizeof(*jagged[0]) will not compile) - but they're jagged-appearing to the bone ;)

Faisal Vali
A: 

The reason you got the error is that you must specify the bounds for at least the outer dimension; i.e.

int jagged[][3] = {{0,1},{1,2,3}};

You cannot have jagged[0] be a 2-element array of int and jagged[1] be a 3-element array of int; an N-element array is a different type from an M-element array (where N != M), and all elements of an array must be the same type.

What you can do is what the others have suggested above and create jagged as an array of pointers to int; that way each element can point to integer arrays of different sizes:

int row0[] = {0,1};
int row1[] = {1,2,3};
int *jagged[] = {row0, row1};

Even though row0 and row1 are different types (2-element vs. 3-element arrays of int), in the context of the initializer they are both implicitly converted to the same type (int *).

John Bode