3

I would like to know if it's possible to create a 2D array in C with different size of lines.

I know a 2D array is an array that stores other arrays. But what if the arrays are size different? Like something like this (a "T" is a usable position of the array)

   0  1  2  3  4
0  T  T  
1  T  T  T  T  T
2  T  T  T
3  T  T  T  T  

If possible, how to do it? Just like a normal 2D array?

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
Maxime Beasse
  • 55
  • 2
  • 12

5 Answers5

10

Arrays of arrays of different size is possible in C. Simply they are not 2D arrays but arrays or pointers. You will find more about the difference in that answer from C tag FAQ.

@vahero has shown how you could dynamically allocate that, but it is also possible with static or automatic storage:

char row0[] = "TT";      // size 3 because of the terminating null...
char row1[] = "TTTTT";
char row2[] = "TTT";
char row3[] = "TTTT";
char* array[] = { row0, row1, row2, row3};

Or without additional variable identifiers:

char *arr[] = { 
    (char[]){ 'T', 'T', 0 },
    (char[]){ 'T', 'T', 'T', 'T', 'T', 0 },
    (char[]){ 'T', 'T', 'T', 0 },
    (char[]){ 'T', 'T', 'T', 'T', 0 },
};

You can then use is as usual:

for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++) {
    for(int j=0; arr[i][j] != '\0'; j++) {
        printf("%c ", arr[i][j]);
    }
    printf("\n");
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
2

IMO the best solution indeed is to make an array of a structure of the following type:

struct arbitrary_len_arr {
    int len;
    int* arr;
};

The beautiful thing with this implementation is that, once you make your 2D array to use these structs as pointers for each row, you can then update your arr pointer to point to whatever array length you want so long as you update its len member. So what you would do is:

struct arbitrary_len_arr* my_arr = malloc(sizeof(struct arbitrary_len_arr) * N);

Where N is how many rows you want. Then when you fill them you'll have to also fill the members accordingly, like so:

my_arr[i].len = M;
my_arr[i].arr = malloc(sizeof(int) * M;

In some loop probably. Then you'll have your arbitrary length arrays.

SenselessCoder
  • 1,139
  • 12
  • 27
0

I presume that you mean pointer to pointers. (In the future please try to use appropriate tag markers. You can check by clicking the tag.)

But yes! There is nothing stopping you from doing:

int **pointerToPointers = malloc(length*sizeof(int *));
pointerToPointers[xUnderLength] = malloc(arbitaryLength*sizeof(int));
vahvero
  • 525
  • 11
  • 24
0

Of course you can create such a structure, but you would have to determine/save the number of columns per row. For example

size_t cols_per_row [] = { 2, 5, 3, 4 };

int **arr2d = calloc(sizeof cols_per_row / sizeof *cols_per_row, sizeof *arr2d);

for(size_t i = 0; i < sizeof cols_per_row / sizeof *cols_per_row; ++i)
    arr2d[i] = calloc(cols_per_row[i], sizeof *arr2d[i]);

I omitted the error checkings for when calloc returns NULL in order to demonstrate the principle in fewer lines.

Note that I used calloc instead of malloc, because calloc sets the memory to 0, which is nice for initialization.

Pablo
  • 13,271
  • 4
  • 39
  • 59
0

If you mean can you declare one dimension to have a variable sized element, then the answer is no. C doesn't support dynamically sized structures, so you couldn't allocate them in an array as such without scaling the space for your largest element. However, there are ways and means. You could allocate a block of space and only use what you need, not very efficient. You could use a union to have elements of a variety of types but a fixed size. The main thing is you have a fixed stride value in C, so the elements will all need to comply with that stride value. That is if the data is to go inside the array structure.

The above solution proposes an alternative solution whereby your structure stores a pointer to data stored elsewhere. That's not to my mind what you were asking, but it's a solution to the problem. You could store links to the data elements that are allocated on demand. The array then becomes more of an index than a storage structure. I operate typically in non-dynamically allocated environments like MISRA. If I say something has to be "in" an array I would assume you mean all data inside the defined memory of that object. So the answer to that is no, if you are willing to allow the data to be indexed... well yeah... If you are happy to have wasted space, again, yeah... but not packed variable sized data elements in a C array object.

Rob
  • 141
  • 5