0
void alloc_matrix(int ***mat, int *m, int *n) {
    mat = (int **)malloc(*m * sizeof(int *));

    for(int i = 0; i < *m; i++)
        mat[i] = (int *)malloc(*n * sizeof(int));

    for(int i = 0; i < *m; i++)
        for(int j = 0; j < *n; j++)
            scanf("%d", &mat[i][j]);

    for(int i = 0; i < *m; i++)
        for(int j = 0; j < *n; j++) {
            printf("%d ", mat[i][j]);
            printf('\n');
        }

}

i wanted to read and allocate the matrix in the same function, but when i call it, nothing will print, i think there is something wrong with the way i used the pointers, but i cant figure out what is the problem

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
MXF
  • 1
  • 1
  • Possible dupe? [**Correctly allocating multi-dimensional arrays**](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) – Andrew Henle Dec 02 '22 at 18:46
  • "i wanted to read and allocate the matrix in the same function" Not the best idea. Separation of concerns is the name of the game in programming. A function should do one thing and do it well. – n. m. could be an AI Dec 02 '22 at 18:47
  • But the first error is in the first line, and your compiler should have warned you about it. If not, you should uninstall it and download a modern compiler. – n. m. could be an AI Dec 02 '22 at 18:49
  • See [here](https://godbolt.org/z/4dehK7Ej4). For more info, see [here](https://stackoverflow.com/questions/57842756/why-should-i-always-enable-compiler-warnings). – n. m. could be an AI Dec 02 '22 at 18:53
  • 1
    Finally, functions in C are able to *return values*. Take advantage of it. Does `malloc` receive a pointer argument? No, it returns a value. Your function should do the same. Prefer to return a value over an out-parameter if possible. – n. m. could be an AI Dec 02 '22 at 18:56
  • Heed what @n.m. said - `int **alloc_matrix(int m, int n) { ... }` is a **lot** easier to understand. N.B. - also remove the `int *n` and just use `int n` - you're not changing `m` or `n` in the caller so there's absolutely no need for the indirection of a pointer. – Andrew Henle Dec 02 '22 at 19:00

1 Answers1

1

The expressions like &mat[i][j] or mat[i][j] used in the for loops and the expression mat used in the statement that allocates memory for an array of pointers

mat = (int **)malloc(*m * sizeof(int *));

for(int i = 0; i < *m; i++)
    mat[i] = (int *)malloc(*n * sizeof(int));

for(int i = 0; i < *m; i++)
    for(int j = 0; j < *n; j++)
        scanf("%d", &mat[i][j]);

for(int i = 0; i < *m; i++)
    for(int j = 0; j < *n; j++) {
        printf("%d ", mat[i][j]);
        printf('\n');
    }

are incorect.

Instead you have to write

*mat = (int **)malloc(*m * sizeof(int *));

for(int i = 0; i < *m; i++)
    ( * mat )[i] = (int *)malloc(*n * sizeof(int));

for(int i = 0; i < *m; i++)
    for(int j = 0; j < *n; j++)
        scanf("%d", &( *mat )[i][j]);

for(int i = 0; i < *m; i++)
{
    for(int j = 0; j < *n; j++) {
        printf("%d ", ( *mat )[i][j]);
    }
    printf( "\n" );
}

That is the parameter mat has the type int ***. This means that the original pointer of the type int ** is passed to the function by reference indirectly through a pointer to it. Thus you need to dereference the parameter to get an access to the original pointer.

And this call of printf

printf('\n');

where you are incorrectly using the integer character constant '\n' instead of the string literal "\n" should be placed after the inner for loop.

Also there is no sense to declare m and n as pointers. The function could be declared at least like

void alloc_matrix(int ***mat, int m, int n) {

Here is a demonstration program

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

void alloc_matrix( int ***mat, int m, int n ) 
{
    *mat = ( int ** )malloc( m * sizeof( int * ) );

    for (int i = 0; i < m; i++)
        ( * mat )[i] = ( int * )malloc( n * sizeof( int ) );

    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            scanf( "%d", &( *mat )[i][j] );

    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++) {
            printf( "%d ", ( *mat )[i][j] );
        }
        putchar( '\n' );
    }
}

int main( void )
{
    enum { M = 2, N = 3 };
    int **mat = NULL;

    alloc_matrix( &mat, M, N );

    for (int i = 0; i < M; i++)
    {
        free( mat[i] );
    }
    free( mat );
}

Its output might look like

1 2 3
4 5 6
1 2 3
4 5 6

The first two lines is the user input and the next two lines is the output of elements of the dynamically allocated arrays.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • It still wont let me read the elements of the matrix – MXF Dec 02 '22 at 18:47
  • when i run this it gives an error on line free(mat[i]), it says the value is neither an array nor a pointer; also, is it mandatory to initialize the matrix with NULL in main? cant i do it in the function? – MXF Dec 02 '22 at 19:46
  • @MXF Please at least copy and paste the demonstration program as is. Can you? – Vlad from Moscow Dec 02 '22 at 19:48
  • I'd also through in the cast of `malloc()` being unnecessary. And even add that if you are casting to get around a compiler warning -- that should tell you you have other problems to fix. See: [Do I cast the result of malloc?](http://stackoverflow.com/q/605845/995714) – David C. Rankin Dec 02 '22 at 19:54
  • what my challenge is it says each time i input the character L in main, i read m and n (rows and columns for a matrix) then i allocate dynamically that matrix; i do this over and over, i can read as many characters as i want. my problem is how do i reallocate the memory for each new matrix, do i use realloc() after scanf inside the fucntion or? – MXF Dec 02 '22 at 20:35
  • @MXF You can free the already allocated matrix as shown in the demonstration program and allocate a new matrix using the function. – Vlad from Moscow Dec 02 '22 at 20:43