Home > Back-end >  Trying to allocate and set to 0 a matrix dynamically in C, but I can't get the set to 0 part to
Trying to allocate and set to 0 a matrix dynamically in C, but I can't get the set to 0 part to

Time:09-01

I have this matrix initialization function I need: I can generate it without any problems but can't initialize all its values to 0, neither with calloc or via looping on the matrix elements.

The function is as follows:

int initMTX(int r, int c, int ***MTX) {
  int **locMTX = malloc(r * sizeof(int *)), i, j;
  for (i = 0; i < r; i  ) {
    locMTX[i] = (int *)malloc(c * sizeof(int));
  }
  for (i = 0; i < r; i  )
    for (j = 0; j < c; j  )
      locMTX[i][j] = 0;
  *MTX = locMTX;

  return 1;
}

If needed for context, the entire code is this:

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

int initMTX(int r, int c, int ***MTX);
void printMTX(int r, int c, int **MTX);
void freeMTX(int r, int **MTX);

int main(void) {
  int NBits = 4, NNumbers = 2 ^ NBits, **MTXResults;
  initMTX(NNumbers, NBits, &MTXResults);
  // code
  printMTX(NNumbers, NBits, MTXResults);
  freeMTX(NNumbers, MTXResults);
}

int initMTX(int r, int c, int ***MTX) {
  int **locMTX = malloc(r * sizeof(int *)), i, j;
  for (i = 0; i < r; i  ) {
    locMTX[i] = (int *)malloc(c * sizeof(int));
  }
  for (i = 0; i < r; i  )
    for (j = 0; j < c; j  )
      locMTX[i][j] = 0;
  *MTX = locMTX;
  return 1;
}

void printMTX(int r, int c, int **MTX) {
  int i, j;
  for (i = 0; i < r; i  ) {
    for (j = 0; j < c; j  )
      printf("%d ", MTX[i][r]);
    printf("\n");
  }
}

void freeMTX(int r, int **MTX) {
  for (int i = 0; i < r; i  )
    free(MTX[i]);
  free(MTX);
}

I thought I grasped such a thing well by now, but it turns out it is not the case, so I've been stuck for a while. If possible I would appreciate also knowing where the problem is when using calloc too.

CodePudding user response:

If your compiler supports Variable Length Arrays, this can be used.

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

void printMTX(int r, int c, int (*MTX)[c]);

int main(void) {
    int NBits = 4;
    int NNumbers = NBits * NBits;
    int (*MTXResults)[NBits];
    if ( NULL == ( MTXResults = calloc( sizeof *MTXResults, NNumbers))) {
        fprintf ( stderr, "problem calloc\n");
        return 1;
    }
    printMTX(NNumbers, NBits, MTXResults);
    free ( MTXResults);
}

void printMTX(int r, int c, int (*MTX)[c]) {
    int i, j;
    for (i = 0; i < r; i  ) {
        for (j = 0; j < c; j  ) {
            printf("%d ", MTX[i][j]);
        }
        printf("\n");
    }
}

CodePudding user response:

This code fixes the bugs in the code in the question (most notably the typo MTX[i][r] becomes MTX[i][j]), and implements freeMTX(). It also includes the code to recover from a memory allocation failure while creating the matrix.

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

int initMTX(int r, int c, int ***MTX);
void printMTX(int r, int c, int **MTX);
void freeMTX(int r, int **MTX);

int main(void)
{
    int NBits = 4;
    int NNumbers = 16;
    int **MTXResults;

    if (initMTX(NNumbers, NBits, &MTXResults))
    {
        printMTX(NNumbers, NBits, MTXResults);
        freeMTX(NNumbers, MTXResults);
    }
    else
        fprintf(stderr, "failed to allocate %dx%d matrix\n", NBits, NNumbers);
}

int initMTX(int r, int c, int ***MTX)
{
    int **locMTX = malloc(r * sizeof(int *));
    if (locMTX == 0)
        return 0;
    for (int i = 0; i < r; i  )
    {
        locMTX[i] = (int *)malloc(c * sizeof(int));
        if (locMTX[i] == 0)
        {
            for (int j = 0; j < i; j  )
                free(locMTX[j]);
            free(locMTX);
            return 0;
        }
    }
    for (int i = 0; i < r; i  )
    {
        for (int j = 0; j < c; j  )
            locMTX[i][j] = 0;
    }

    *MTX = locMTX;
    return 1;
}

void printMTX(int r, int c, int **MTX)
{
    for (int i = 0; i < r; i  )
    {
        for (int j = 0; j < c; j  )
            printf("%d ", MTX[i][j]);
        printf("\n");
    }
}

void freeMTX(int r, int **MTX)
{
    for (int i = 0; i < r; i  )
        free(MTX[i]);
    free(MTX);
}

This code uses the simpler, two allocation scheme outlined in two comments:

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

int initMTX(int r, int c, int ***MTX);
void printMTX(int r, int c, int **MTX);
void freeMTX(int **MTX);

int main(void)
{
    int NBits = 4;
    int NNumbers = 16;
    int **MTXResults;

    if (initMTX(NNumbers, NBits, &MTXResults))
    {
        printMTX(NNumbers, NBits, MTXResults);
        freeMTX(MTXResults);
    }
    else
        fprintf(stderr, "failed to allocate %dx%d matrix\n", NBits, NNumbers);
}

int initMTX(int r, int c, int ***MTX)
{
    int **locMTX = malloc(r * sizeof(locMTX[0]));
    if (locMTX == 0)
        return 0;
    int *data = malloc(r * c * sizeof(locMTX[0][0]));
    if (data == 0)
    {
        free(locMTX);
        return 0;
    }
    for (int i = 0; i < r; i  )
    {
        locMTX[i] = data   i * c;
        for (int j = 0; j < c; j  )
            locMTX[i][j] = 0;
    }

    *MTX = locMTX;
    return 1;
}

void printMTX(int r, int c, int **MTX)
{
    for (int i = 0; i < r; i  )
    {
        for (int j = 0; j < c; j  )
            printf("%d ", MTX[i][j]);
        printf("\n");
    }
}

void freeMTX(int **MTX)
{
    free(MTX[0]);
    free(MTX);
}

The freeing code is much simpler, as is the error recovery while creating the matrix — mainly because there are only two allocations that can fail.

  • Related