3

currently i'm learning about pointers.

   mat3 = (double***) malloc(m*sizeof(double**));

This statement indicates that mat3 points to the first array of the two arrays that contain double**.

mat3[0] = (double**) malloc(m*n*sizeof(double*));

I made a small figure to show how I see this. I don't understand why the line with the comment is wrong. In my opinion the same happens as the one above.

   for (i=0; i<m; i++)
   {
      mat3[i] = mat3[0] + i*n;
      for(j=0; j<n; j++)
      {
         mat3[i][j] = mat3[i][0] + j*p; // this goes wrong
      }
   }

In the first loop the adress of the first ** array taken and each iteration 3 is added. The figure also shows that there are 3 * arrays, so that looks OK.

In the second loop the adress of the first * array is taken and each iteration 4 is added. That also looks okay since each * array contains 4 places to store a double. So 4 memory places needs to be skipped.

There is something wrong, but I don't see it. Can I get feedback?

enter image description here

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

int main()
{
   double*** mat3;
   int m,n,p;
   int i,j,k;
   
   m=2; n=3; p=4;

   printf("This program causes a coredump, unless you fix the error in it !\n");
   
   mat3 = (double***) malloc(m*sizeof(double**));
   if (mat3 == NULL)
      exit(1);
   
   mat3[0] = (double**) malloc(m*n*sizeof(double*));
   if (mat3[0] == NULL)
      exit(1);
   
   mat3[0][0] = (double*) malloc(m*n*p*sizeof(double));
   if (mat3[0][0] == NULL)
      exit(1);
   
   for (i=0; i<m; i++)
   {
      mat3[i] = mat3[0] + i*n;
      for(j=0; j<n; j++)
      {
         mat3[i][j] = mat3[i][0] + j*p; // this goes wrong
      }
   }
   
   for(i=0;i<m;i++)
      for(j=0;j<n;j++)
         for(k=0;k<p;k++)
             mat3[i][j][k] = i + 10*j + 100*k;
   
   for(i=0;i<m;i++)
      for(j=0;j<n;j++)
         for(k=0;k<p;k++)
             printf("mat3[%d][%d][%d] = %lf\n",i,j,k,mat3[i][j][k]);
   
   exit(0);
}
Tim
  • 415
  • 2
  • 10

3 Answers3

1

Think about how each pointer is initialized and which pointer points to which object.

Start like this. After mat3 = malloc(m*sizeof(double**)); ,mat3 points to an array of length 6 with the elements pointer to pointer to double.

 mat3 (double ***)
   |
   V
+----+----+
|    |    |   (double **) //uninitialized
+----+----+

After the next malloc(), there is a different situation.

  mat3 (double ***)
   |
   V
+----+----+
|    |    | (double **) //uninitialized except element 0
+----+----+
   |
   V
+----+----+----+----+----+----+
|    |    |    |    |    |    |  (double *) //uninitialized
+----+----+----+----+----+----+

Continue this diagram and draw one for each change (just the principle, no need to draw all 24 boxes for the 24 double). When a pointer is set to a wrong value, you know where the error is and how to fix it. I know where the problem is, after i thought about it for a while, and how to fix it, but you should learn to solve this problem on your own.

Off-Topic: Array indexes should never be of type int, use size_t for positive values or ptrdiff_t when you need code that also works with negative indexes.

1

Below is a diagram of what you are trying to create:

enter image description here

The green arrows show the 3 pointers that was initialized using the malloc calls.

The red arrows show the 6 pointers that has not been initialized at this point.

So the code after the 3 malloc must initialize all the red pointers before using them. And your code doesn't do that.

The line mat3[i] = mat3[0] + i*n; will initialize mat3[1].

Then the line mat3[i][j] = mat3[i][0] + j*p; uses mat3[0][0] and mat3[1][0] on the rigth hand side. Use of mat3[0][0] is fine as it has been initialized but use of mat3[1][0] is bad as it's uninitialized.

Change

mat3[i][j] = mat3[i][0] + j*p;

to

mat3[i][j] = mat3[0][0] + i*n*p + j*p;
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • Really helpful! Thanks for taking time to make a figure! – Tim Oct 13 '20 at 08:22
  • You are correct, but i am not sure if you should just present the right answer for such a question. Since he is still learning it would probably better to only say how he can find the answer. – 12431234123412341234123 Oct 13 '20 at 10:43
0

Please correct me if I am wrong, but sizeof(double*), sizeof(double**), sizeof(double***), sizeof(double****) ..., return the same number of bytes( size of the memory address supported).