1

I have to create a matrix but with the following requirements:

  • create a function for it
  • the matrix has to be dynamic allocated inside the function
  • the matrix has to be returned as a parameter of the function (function has to be void)

What I tried:

void createMatrix(int n,float** matrix)
{

    matrix = (float**)malloc(n * sizeof(float*));
    for (int i = 0; i < n; i++)
        matrix[i] = (float*)malloc(n* sizeof(float));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            matrix[i][j] = 0;
}
int main()
{
    int n;
    FILE* fis;
    fis = fopen("fileIn.txt", "r");
    if (!fis)
    {
        printf("File not opened");
        return;
    }
    fscanf(fis, "%d", &n);
    fclose(fis);
    float** matrix;
    createMatrix(n, &matrix);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            printf("%f ", matrix[i][j]);
        printf("\n");
    }
    return;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

4 Answers4

1

If you're passing the address of a float ** to a function, the type of the parameter should be float ***. So in the function, change the parameter type to that and use *matrix wherever matrix was used.

void createMatrix(int n, float ***matrix)
{

    *matrix = malloc(n * sizeof(float*));
    for (int i = 0; i < n; i++)
        (*matrix)[i] = malloc(n* sizeof(float));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            (*matrix)[i][j] = 0;
}

Note that the casts have also been removed, as casting the return value of malloc is not necessary and can mask other errors in your code.

You also should add error checking after the calls to malloc.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Why would someone ever want to allocate a square 2D matrix like this? – Lundin Jan 27 '22 at 15:23
  • @Lundin It's not the most efficient in terms of memory, but it directly addresses OP's issues. – dbush Jan 27 '22 at 15:24
  • But if there doesn't exist a single technical/practical reason for doing it like this, why would anyone want to do it? The OP is likely a beginner, we should teach them how to allocate arrays correctly. – Lundin Jan 27 '22 at 15:26
1

If you are creating the matrix such a way

matrix = (float**)malloc(n * sizeof(float*));
for (int i = 0; i < n; i++)
    matrix[i] = (float*)malloc(n* sizeof(float));
for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
        matrix[i][j] = 0;

and want to return the matrix through a parameter then the function should be declared like

void createMatrix( int n, float ***matrix )
{
    *matrix = malloc( n * sizeof( float* ) );

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

    for ( int i = 0; i < n; i++ )
    {
        for ( int j = 0; j < n; j++ )
        {
            ( *matrix )[i][j] = 0;
        }
    }
}

That is if you are passing the pointer matrix declared in main like

float** matrix;

to the function by reference through a pointer to it

createMatrix(n, &matrix);

then the corresponding function parameter will have the type float ***.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Why would someone ever want to allocate a square 2D matrix like this? – Lundin Jan 27 '22 at 15:23
  • @Lundin Firstly not all compilers support variable length arrays. And secondly of course it is much better when the result pointer is returned from the function. – Vlad from Moscow Jan 27 '22 at 15:37
  • You don't need to use VLA to do something like `float (*fmat)[42] = calloc( 1, sizeof(float[42][42]) );`. Either way, it's best to upgrade to a standard C compiler with VLA support. – Lundin Jan 27 '22 at 15:41
1

Some things to note:

  • Your function is creating a pointer-to-pointer look-up table, not a 2D array. Pointer-to-pointer look-up tables only make sense when we want individually-sized items, which is never the case in a mathematical, square-shaped matrix. All the pointer-to-pointer trick achieves is bloat, slow access and needless complexity. You gain absolutely no advantages from it. For details see Correctly allocating multi-dimensional arrays
  • This look-up table is assigned to the local variable matrix and not returned from the function, which is a bug and a memory leak.

We can easily fix these bugs and design mistakes if you can drop those requirements you listed. Then there's a much better standard C function for all of this called calloc.

Usage:

size_t fx = 5;
size_t fy = 3;
float (*fmat)[fy] = calloc( 1, sizeof(float[fx][fy]) );
...
free(fmat);

This is much faster than your function, it doesn't come with needless type-generic programming, it allocates a true 2D array in contiguous memory which gives data cache coherence and it sets all data items to zero.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

You'll need to change createMatrix as follows:

void createMatrix(int n,float*** matrix)
{
    *matrix = (float**)calloc(n,sizeof(float*));
    for (int i = 0; i < n; i++)
        *matrix[i] = (float*)calloc(n,sizeof(float));
}

In order for the caller to be able to see the matrix you create, you have to pass a pointer to it... yes, that is a pointer-to-a-pointer-to-a-pointer. And by using calloc instead of malloc, the initialization to zero is handled for you.

SGeorgiades
  • 1,771
  • 1
  • 11
  • 11