3

I understand that you can easily make a matrix with a fixed length:

double m[][2];

However, I want to have a datastructure which is an array, where I store arrays of double type which have different lengths. How do I do that?

An example would be:

arr1 = {1,2,3,4};
arr2 = {1,2};
osk
  • 790
  • 2
  • 10
  • 31
  • 2
    One solution is an array of *pointers*, where each pointer points to the first element of the sub-array. Of course, then it would not be an array of arrays any longer. – Some programmer dude Sep 09 '17 at 11:13

3 Answers3

7

Jagged arrays are commonly represented as arrays of pointers to pointers in C:

double arr0[] = {4, 1, 7};
double arr1[] = {1, 2, 3, 4};
double arr2[] = {1, 2};
double *m[] = {arr0, arr1, arr2};

Unfortunately, there is no standard syntax for defining inner arrays "in line" with the outer array of pointers.

Note that there is no way to find the length of each inner array now, so you need to add some sort of a "marker", or to store lengths separately:

#define SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
...
size_t len[] = { SIZE(arr0), SIZE(arr1), SIZE(arr2) };
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

It can be done using an array of pointers, i.e.

#include <stdio.h>

int main(void) {
    double* x[2];
    double a[2] = {1.0, 2.0};
    double b[4] = {1.0, 2.0, 3.0, 4.0};
    x[0] = a;
    x[1] = b;

    printf("%f %f\n", x[0][1], x[1][3]);
    return 0;
}

To keep track of the size of arrays (aka the number of elements in the arrays), you could consider using an array of structs. Like:

#include <stdio.h>

struct z
{
    unsigned int size;
    double* p;
};

int main(void) {
    int i, j;
    struct z x[2];
    double a[2] = {1.0, 2.0};
    double b[4] = {1.0, 2.0, 3.0, 4.0};
    x[0].p = a;
    x[0].size = sizeof a / sizeof(double);
    x[1].p = b;
    x[1].size = sizeof b / sizeof(double);

    for (i=0; i<2; ++i)
    {
        for (j=0; j<x[i].size; ++j)
        {
            printf("x[%d][%d] %f\n", i, j, x[i].p[j]);
        }
    }
    return 0;
}

Output:

x[0][0] 1.000000
x[0][1] 2.000000
x[1][0] 1.000000
x[1][1] 2.000000
x[1][2] 3.000000
x[1][3] 4.000000
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
1

You can do this by creating an array of pointers. In this case the elements of the jagged array are not necessarily stored contiguously, and the length of the individual rows must be kept somehow so that the jagged array can be used.

If the array type allows it, another option is to use a 2d array, storing the size of each row in the first element of each row. This will likely use more memory than an array of pointers, but the elements will be stored contiguously in memory.

If there is a value that can't appear in the array, a sentinel value can be used instead of explicitly storing the row sizes. This can be used even if the type of the array won't allow storage of size values (e.g., char[][]).

#include <stdio.h>
#include <string.h>

int main(void)
{
    /* Jagged array using pointers */
    int array_1[] = { 1, 2, 3 };
    int array_2[] = { 5, 6 };
    int array_3[] = { 7, 8, 9, 10 };

    int *jagged_array_1[] = { array_1, array_2, array_3 };
    size_t array_sizes[] = { sizeof array_1 / sizeof *array_1,
                             sizeof array_2 / sizeof *array_2,
                             sizeof array_3 / sizeof *array_3 };

    for (size_t i = 0; i < 3; i++) {
        for (size_t j = 0; j < array_sizes[i]; j++) {
            printf("%4d", jagged_array_1[i][j]);
        }
       putchar('\n');
    }
    putchar('\n');

    /* Using the first element to store sizes */
    int jagged_array_2[3][5] = { { 0 } };

    jagged_array_2[0][0] = sizeof array_1 / sizeof *array_1;
    memcpy(&jagged_array_2[0][1], array_1, sizeof array_1);

    jagged_array_2[1][0] = sizeof array_2 / sizeof *array_2;
    memcpy(&jagged_array_2[1][1], array_2, sizeof array_2);

    jagged_array_2[2][0] = sizeof array_3 / sizeof *array_3;
    memcpy(&jagged_array_2[2][1], array_3, sizeof array_3);

    for (int m = 0; m < 3; m++) {
        for (int n = 0; n < jagged_array_2[m][0]; n++) {
            printf("%4d", jagged_array_2[m][n+1]);
        }
        putchar('\n');
    }
    putchar('\n');

    /* Using a sentinel element */
    int jagged_array_3[3][5] = { { 0 } };

    memcpy(jagged_array_3[0], array_1, sizeof array_1);
    jagged_array_3[0][sizeof array_1 / sizeof *array_1] = -1;

    memcpy(jagged_array_3[1], array_2, sizeof array_2);
    jagged_array_3[1][sizeof array_2 / sizeof *array_2] = -1;

    memcpy(jagged_array_3[2], array_3, sizeof array_3);
    jagged_array_3[2][sizeof array_3 / sizeof *array_3] = -1;

    for (size_t i = 0; i < 3; i++) {
        for (size_t j = 0; jagged_array_3[i][j] != -1; j++) {
            printf("%4d", jagged_array_3[i][j]);
        }
        putchar('\n');
    }
    putchar('\n');

    return 0;
}
ad absurdum
  • 19,498
  • 5
  • 37
  • 60