1

I have been working on a code displaying the result of transposing 2D arrays containing integers. My aim was to replace the original array with its transpose rather than create a copy and I have run into a problem along the way regarding memory allocation. In the beginning I get number of rows (m) and columns (n) via scanf() and then allocate memory for the array in the main() function as below:

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

Then I call my function for transposing arrays that looks as follows:

void transposeMatrix(int m,int n,int mtr[m][n])
{
    int temp[m][n];
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            temp[i][j]=mtr[i][j];
        }
    }
    for(int i=0;i<m;i++)
        free(mtr[i]);
    free(mtr);
    mtr=(int **)malloc(n*sizeof(int *));
    for(int i=0;i<n;i++)
        mtr[i]=(int *)malloc(m*sizeof(int));
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            mtr[i][j]=temp[j][i];
        }
    }
}

My aim was to first store the values of original 'mtr' in temporary 'temp' array, then free memory allocated to 'mtr' and then allocate memory once more switching rows with columns in order to use the same 'mtr' back in the main(). However at line:

mtr[i]=(int *)malloc(m*sizeof(int));

I get "error:assignment to expression with array type". Shouldn't mtr[i] by freed at that point? Does anyone know where the problem might be?

AndrewZ
  • 13
  • 2

2 Answers2

2

This:

int **mtr /* ... */;

Declares a pointer to a pointer to int. The target pointer might be the first in an array of such pointers, but under no circumstances is there a 2D array involved here. A 2D array is an array of arrays, which has all the member arrays contiguous in memory. That is not guaranteed with an array of pointers to arrays (only the pointers must be contiguous, not the objects to which they point). Moreover, the mtr pointer cannot be directly converted to a pointer to the first int of the array pointed to by the first element.

You can use the pointer to pointer array form in many of the same ways that you can use a bona fide 2D array, but as an argument to this function is not one of them:

void transposeMatrix(int m,int n,int mtr[m][n])

Your compiler ought to be emitting warnings about that. The easiest solution for you, at least to get you over the first hurdle, would be to declare the function as accepting an argument of the correct type:

void transposeMatrix(int m,int n,int **mtr) { // ...

You'll still run into trouble with that, however, because although the function can reallocate or free + malloc the memory to which its mtr parameter points, that does not modify the caller's copy of that pointer. There are two ways to get around that:

  1. Declare the function to accept a pointer to the caller's pointer, or
  2. Have the function return the modified pointer value.

Implementing the latter would require fewer changes to your code:

int **transposeMatrix(int m,int n,int **mtr) {
    // ...
    return mtr;
}

// ...

// call the function as:
mtr = transposeMatrix(m, n, mtr);
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

Along with suggestions from John Bollinger above, I would like to add one more. There is no need to free mtr. Just free mtr[i] and reallocate mtr[i]. The point is to transpose row to columns. Freeing up mtr in a function could end up undefined behavior since mtr was allocated in main() or where ever. The address of mtr was sent to a function. But if you deallocate and reallocate memory of mtr in this function, I don't think this is safe thing to do.

void transposeMatrix(int m,int n,int **mtr)
{
   int temp[m][n];
   for(int i=0;i<m;i++)
   {
       for(int j=0;j<n;j++)
       {
        temp[i][j]=mtr[i][j];
       }
   }

   for(int i=0;i<m;i++)
       free(mtr[i]);
   //free(mtr);    <== Don't need to free
   //mtr=(int **)malloc(n*sizeof(int *));

  for(int i=0;i<n;i++)
       mtr[i]=(int *)malloc(m*sizeof(int));
  for(int i=0;i<n;i++)
  {
    for(int j=0;j<m;j++)
    {
        mtr[i][j]=temp[j][i];
    }
  }
}
Nguai al
  • 958
  • 5
  • 15