0

I am new to C language and I try to write function to allocate memory for 2d array What am I doing:

void allocate(int **arr, int r, int c) 
{
    **arr = (int **)malloc(r*c*sizeof(int));
}
    int main( void )
{
    int NO_OF_COLS = 0;
    int NO_OF_ROWS = 0;    
    scanf("%d%d", &NO_OF_ROWS, &NO_OF_COLS);

    int **matrix;
    
    allocate(matrix, NO_OF_ROWS, NO_OF_COLS);

    return 0;
}

I have this warning: assignment to 'int' from 'int **' makes integer from pointer without a cast [-Wint-conversion] 8 | **arr = (int **)malloc(rcsizeof(int)); | ^

I understand that I am passing memory to 'matrix' in allocate(), but I don't understand how I can return new memory address and assign it to matrix

I try to change allocate(matrix, NO_OF_ROWS, NO_OF_COLS); to allocate(&matrix, NO_OF_ROWS, NO_OF_COLS); but it still doesn't work

  • 1
    Using 2 stars doesn't give you a 2D matrix so simply. If you want a single allocation then you'll need a 1D array and to figure out the indexing yourself. If a 2D array then you need first to allocate an array of pointers, then each with an allocation to a 1-D array. – Weather Vane Oct 07 '21 at 08:26
  • you need to allocate 1-D array of pointers, each entry of which will be another 1-D array of ints – Nikos M. Oct 07 '21 at 08:32
  • You might want something like `int (*matrix)[NO_OF_COLS] = malloc(NO_OF_ROWS * sizeof *matrix);` – mediocrevegetable1 Oct 07 '21 at 08:33
  • 1
    Does this answer your question? [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) – tstanisl Oct 07 '21 at 09:30

2 Answers2

0

First of all you need to allocate an array of arrays to hold the data. You need to allocate an array to hold N elements of pointer type. Consider this:

int** allocate(int row, int col)
{
    int i;
    int** a = (int**) malloc(row * sizeof(int*));
    if (!a)
        return  0;

    for(i=0; i < row; i++) {
        a[i] = (int*) malloc(sizeof(int) * col);
    }
    return  a;
}

You need to allocate a to hold N elements that are pointers to int arrays, then loop and allocate the actual array needed ( sizeof(int) * col ) in your use case. So here is in use:

int main()
{
    int** a= allocate(10, 10);
    int i=0, j=0;
    for(i=0; i < 10; i++) {
        for(j=0; j < 10; j++) {
            a[i][j] = 42;
        }
    }

    for(i=0; i < 10; i++) {
        for(j=0; j < 10; j++) {
            printf("[%d]", a[i][j]);
        }
        puts("");
    }
    return 0;
}

Also you need to write a deallocation function the same way, but first you have to loop trough all elements and free the arrays before freeing the a array in your case. [EDIT]: I haven't added a fail safe check to the second malloc for simplicity. Given that example and that function prototype you need to allocate a 1D array as:

void allocate(int** a, int row, int col)
{
    *a = malloc(sizeof(int) * row * col);
}

But it's a different than allocating arrays of arrays.

Ilian Zapryanov
  • 1,132
  • 2
  • 16
  • 28
  • On assigment I can't change type of function allocate() – SilverMoon17 Oct 07 '21 at 09:32
  • If this is some homework or exercise, you can use mine as a helper to call inside the original one. `void allocate(int** a, int row, int col) { a = allocate_internal(row, col); ... ` but you'd better to understand `C` allocations before doing such tasks or exercises. – Ilian Zapryanov Oct 07 '21 at 09:37
  • Given your example I suggest you need to allocate a 1D array of ints with size of row x col, which is different that 2D array. I presume in your case you need to just alloc: `void allocate(int** a, int row, int col) { *a = malloc(sizeof(int) * row * col); } ` which is not a 2D array but 1D. – Ilian Zapryanov Oct 07 '21 at 09:55
0

Since you can't modify the parameters for allocate, you will need to manually compute the index of each element in the matrix. The following bare-bones program shows how to access each element of a 5 x 5 matrix.

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

void allocate(int **arr, int r, int c)
{
        *arr = malloc(sizeof (int) * r * c); 
}

int main(void)
{
        int *arr = NULL;
        int NO_OF_ROWS = 5, NO_OF_COLS = 5;
        allocate(&arr, NO_OF_ROWS, NO_OF_COLS);

        for (int r = 0; r < NO_OF_ROWS; ++r) {
              for (int c = 0; c < NO_OF_COLS; ++c) {
                    printf("arr[%d]\n", r * NO_OF_COLS + c); 
              }   
        }   
}

Here, we are actually using a 1-D array. Inside the loop, r * NO_OF_COLS + c is responsible for accessing each element. This program will print arr[0], arr[1]...arr[24]. You may use this logic to calculate the index of each element.

Inside main(), arr is just a pointer to an int. When we pass the address of arr to allocate(), we are giving allocate() a chance to modify arr. Then, inside allocate(), we hop to the address that was passed in and lay down the bits returned by malloc.

babon
  • 3,615
  • 2
  • 20
  • 20