0

I am working on a Matrix Multiplication problem and I am dynamically allocating arrays

Here is what I currently have:

global:

int **a;

in my allocatematrix function: (m - row, k - col)

    a = (int **)malloc(m * sizeof(int *));
    for (i=0; i<m; i++)
    {
         a[i] = (int *)malloc(k * sizeof(int));
    }

    // Note that arr[i][j] is same as *(*(arr+i)+j)
    // just to test my array allocation is working
    for (i = 0; i < m; i++)
    {
      for (j = 0; j < k; j++)
      {
         a[i][j] = ++count;  // OR *(*(arr+i)+j) = ++count
      }
    }


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

    // I would like to pass my pointer to pointer
    // into a subroutine, such that it transforms the 
    // the global double array, but it keeps blowing up here
    loadMatrix(fp, &a, m, k);

load matrix function:

// read in the file
void loadMatrix(FILE *fp, int ***arr, int size1, int size2)
{
    //fp = fopen(name, "r");
    if (fp == NULL)
    {
        printf("Error while opening file!\n");
        exit(0);
    }

    int i, j;
    for(i = 0; i < size1; i++)
    {
        for(j = 0; j < size2; j++)
        {
            int value = 0;
            fscanf(fp, "%d", &value);
            printf("Current Value: %d\n", value);
            //value =  (((arr + i)) + j);
            // line below is where I think I have the issue 
            *(*(*(arr+i)+j)) = value;
        }
    }
}

sample run: with this line commented ((*(arr+i)+j)) = value;

3 2 3 
1 2 
3 4 
5 6 
Current Value: 1
Current Value: 4
Current Value: 2
Current Value: 5
Current Value: 3
Current Value: 6

with out commented out:

3 2 3 
1 2 
3 4 
5 6 
Current Value: 1
Current Value: 4
Current Value: 2
Segmentation fault (core dumped)

1 Answers1

0

You don't need a int *** pointer, if you are passing a pointer, the data it points to will be modified by the function, what you can do is this

// read in the file
void loadMatrix(FILE *fp, int **arr, int size1, int size2)
{
    if (arr == NULL)
        return;
    if (fp == NULL)
    {
        printf("Error while opening file!\n");
        exit(0);
    }

    int i, j;
    for (i = 0 ; i < size1 ; i++)
    {
        for (j = 0 ; j < size2 ; j++)
        {
            int value = 0;
            /* test that fscanf() succeeded reading an integer */
            if (fscanf(fp, "%d", &arr[i][j]) != 1)
                arr[i][j] = 0; /* this just prevents that arr[i][j] be uninitialized */
        }
    }
}

Where you say you test your allocation is working, that doesn't test anything, the only test you can performa is the return value from malloc(), if the allocation fails it returns NULL, so testing that your allocation worked is done like this

a = malloc(m * sizeof(int *));
if (a == NULL)
    pleaseDoSomethingAboutIt_AllocationFailed_DoNotContinue();
for (i = 0 ; i < m ; i++)
{
     a[i] = malloc(k * sizeof(int));
     if (a[i] == NULL)
     {
         while (--i)
             free(a[i]);
         free(a);
         pleaseDoSomethingAboutIt_AllocationFailed_DoNotContinue();
     }
}

If the allocation fails, and you still dereference the pointer, like in your test, you will invoke undefined behavior, and hence you can't test for anything, because you can't know what is going to happen.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • Nice! It worked! So could you possibly explain why they probably suggested a triple pointer for this function? – linkedlist Feb 15 '15 at 03:36
  • No I can't, using a triple pointer makes no sense at all, unless you do both, the allocation and initialization in the same function, but still, since you can return the pointer, i don't see a good reason to pass it as a parameter. There are situations where triple pointers are useful, specially as function parameters, but this is not one of them. – Iharob Al Asimi Feb 15 '15 at 03:38