Search code examples
cdynamic-memory-allocationcallocvariable-length-array

How to create variable length array on heap?


I used C's variable length array to implement an algorithm:

int matrix[rows][cols];

I managed to test that this does fail for ridiculous dimensions. Is there a way to allocate this matrix on heap instead of stack? Otherwise I'll have to rewrite this to int**...

Something like calloc(sizeof(int[rows][cols]), 1)? Note that this question is specifically about variable length arrays.


Solution

  • It looks simple enough. The only remotely tricky bit is the type to hold the pointer to the dynamically allocated array:

    #include <stdlib.h>
    #include <stdio.h>
    
    static void print_matrix(int r, int c, int matrix[r][c])
    {
        for (int i = 0; i < r; i++)
        {
            for (int j = 0; j < c; j++)
                printf(" %d", matrix[i][j]);
            putchar('\n');
        }
    }
    
    static void set_matrix(int r, int c, int matrix[r][c])
    {
        for (int i = 0; i < r; i++)
        {
            for (int j = 0; j < c; j++)
                matrix[i][j] = (i+1) * 100 + j + 1;
        }
    }
    
    int main(void)
    {
        size_t rows = 9;
        size_t cols = 7;
        size_t size = sizeof(int[rows][cols]);
        printf("rows = %zu, cols = %zu, size = %zu\n", rows, cols, size);
        int (*matrix)[cols] = calloc(sizeof(int[rows][cols]), 1);
        if (matrix != 0)
        {
            set_matrix(rows, cols, matrix);
            print_matrix(rows, cols, matrix);
            free(matrix);
        }
        return 0;
    }
    

    This code carefully uses calloc() to zero all the elements of the array, and then calls set_matrix() to set them to non-zero values. As written, malloc() would be better than calloc(), but the question used calloc() and it would not be hard to make it sensible for use with this code too (for example, a conditional assignment in set_matrix(), such as if (i && j && i != j)).

    Example output:

    rows = 9, cols = 7, size = 252
     101 102 103 104 105 106 107
     201 202 203 204 205 206 207
     301 302 303 304 305 306 307
     401 402 403 404 405 406 407
     501 502 503 504 505 506 507
     601 602 603 604 605 606 607
     701 702 703 704 705 706 707
     801 802 803 804 805 806 807
     901 902 903 904 905 906 907