1

I understand that modern C standards lets me allocate a block of memory to a 2d array as follows:

size_t rows, cols;
// assign rows and cols
int (*arr)[cols] = malloc(sizeof(double[cols][rows]));

But is there a way of allocating a block of memory to a 2d array after a declaration? E.g. I have an external variable declared elsewhere I would like to allocate memory to:

size_t rows, cols;
extern int **arr;

//Malloc block to 2d array

I know it's possible to, for example, use a single index in place of 2 [i][j] -> [i*rows + j] but I'm wondering if I can retain the 2 indices?

DJames
  • 463
  • 2
  • 16
  • This is past posts on the same [topic](https://stackoverflow.com/questions/1970698/using-malloc-for-allocation-of-multi-dimensional-arrays-with-different-row-lengt) – Milind Deore Sep 05 '17 at 02:07

2 Answers2

1

Secure the pointer and its pointed area at the same time.

like this

#include <stdio.h>
#include <stdlib.h>

int **arr;

int **Malloc_block_to_2d_array(size_t rows, size_t cols){
    int **arr = malloc(rows * sizeof(*arr) + rows * cols * sizeof(**arr));
    if(arr){
        char *body_top = (char*)arr + rows * sizeof(*arr);
        for(size_t r = 0; r < rows; ++r){
            arr[r] = (int *)(body_top + r * cols * sizeof(**arr));
        }
    }
    return arr;
}

int main(void){
    //DEMO
    size_t rows = 3;
    size_t cols = 5;

    arr = Malloc_block_to_2d_array(rows, cols);
    for(size_t r = 0; r < rows; ++r)
        for(size_t c = 0; c < cols; ++c)
            arr[r][c] = (r+1)*10 + c+1;

    for(size_t r = 0; r < rows; ++r){
        for(size_t c = 0; c < cols; ++c)
            printf("%d ", arr[r][c]);
        puts("");
    }
    free(arr);
}
BLUEPIXY
  • 39,049
  • 7
  • 31
  • 69
1

You cannot "retain" two indexes, because extern int **arr does not declare a contiguous 2D array. It is an array of pointers, so the mechanism of applying two indexes to it used by the compiler is very different from the mechanism used for 2D arrays.

The biggest difference is that accessing 2D array requires the compiler to know the value of cols, while accessing an array of pointers does not.

The declaration

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

is a variable-length array. This is not allowed in static context, so arr cannot be global.

You could make an array of pointers into contiguous block. Two-index expression will work, at the expense of allocating an additional array:

// In the header
extern size_t rows, cols;
extern double **arr;

// In the C file

size_t rows, cols;
double **arr;

void init_array(size_t r, size_t c) {
    rows = r;
    cols = c;
    double (*a)[cols] = malloc(sizeof(double[cols][rows]));
    arr = malloc(rows*sizeof(double*));
    for (size_t i = 0 ; i != rows ; i++) {
        arr[i] = a[i];
    }
}
void free_array() {
    free(arr[0]);
    free(arr);
}

Demo.

Sergey Kalinichenko
  • 697,062
  • 78
  • 1,055
  • 1,465