Search code examples
carraysmultidimensional-arraysignature

How to make a function returning a dynamically-allocated two-dimensional array?


I am trying to return a contiguous memory allocated array from a function but I keep on receiving errors.

Compiler returns a warning saying return from incompatible pointer type [-Wincompatible-pointer-types]

Can someone tell me what I am doing wrong?

int *test() {
    size_t rows, cols;
    // assign rows and cols
    rows = 3;
    cols = 3;
    int count = 0;

    int (*arr)[cols] = malloc(sizeof *arr * rows);
    if (arr) {
        // do stuff with arr[i][j]
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; j++) {
                arr[i][j] = count;
                count++;
            }
            /* code */
        }
    }
    return arr;
}

int main() {    
    size_t rows, cols;
    // assign rows and cols
    rows = 3;
    cols = 3;
    int count = 0;

    int (*arr)[cols] = malloc(sizeof *arr * rows);
    arr = test();

    int i = 0;
    int j = 0;

    for (i = 0; i < rows; ++i) {
        for (j = 0; j < 3; ++j)
            printf("%d ", arr[i][j]);
        printf("\n");
    }
    free(arr);
}

it should return a 2D array but returns an error and am using gcc on ubuntu


Solution

  • Your allocation function is fine, except for a few details:

    • you should pass rows and cols as arguments
    • you should use type size_t for i and j and iterate to rows and cols instead of hard coded bounds.
    • you should use parentheses in malloc(sizeof *arr * rows); for readability: malloc(sizeof(*arr) * rows);
    • you should return &arr[0][0] or arr[0] for type correctness.

    The problem is you cannot define the return type of test to be pointer to 2D array of a parametric second dimension. Hence the type error on the assignment arr = test(); cannot be fixed. You can work around this shortcoming by casting the return value to (int (*)[cols]) or simply (void *).

    Here is a modified version:

    #include <stdio.h>
    #include <stdlib.h>
    
    int *test(size_t rows, size_t cols) {
        int (*arr)[cols] = malloc(sizeof(*arr) * rows);
        if (arr) {
            // initialize the matrix
            size_t count = 0;
            for (size_t i = 0; i < rows; i++) {
                for (size_t j = 0; j < cols; j++) {
                    arr[i][j] = count;
                    count++;
                }
                /* code */
            }
            return &arr[0][0];
        }
        return NULL;
    }
    
    int main() {
        // assign rows and cols
        size_t rows = 3;
        size_t cols = 3;
    
        int (*arr)[cols] = (int (*)[cols])test(rows, cols);
    
        if (arr) {
            for (size_t i = 0; i < rows; i++) {
                for (size_t j = 0; j < cols; j++)
                    printf("%d ", arr[i][j]);
                printf("\n");
            }
            free(arr);
        }
        return 0;
    }
    

    Output:

    0 1 2
    3 4 5
    6 7 8