1

I have this code:

void checkmat(float *** mat,float * max,float * min){

    float sum=0,sum2=0,flag=1;

    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            sum+=(*mat[i][j]);
            sum2+=(*mat[j][i]);
        }
        if(sum>(*max))
            (*max)=sum;
        if(flag){
            (*min)=sum;
            flag=0;
        }
        if(sum2<(*min))
            (*min)=sum2;

    sum=0;
    sum2=0;
    }


}

int main(){

    float mat[n][n]={{1,2,3,4},{5,6,7.6,8},{9,1,2.9,3},{4,5,6,7}};
    float min=0,max=0;

checkmat(&mat,&max,&min);

printf("%f is max %f is min \n",max,min);

}

For now, it doesn't really matter what the code does. I'm interested in why I get this error message from the compiler:

test3.c: In function ‘main’:
test3.c:38:10: warning: passing argument 1 of ‘checkmat’ from incompatible pointer type [-Wincompatible-pointer-types]
 checkmat(&mat,&max,&min);
          ^
test3.c:8:6: note: expected ‘float ***’ but argument is of type ‘float (*)[4][4]’
 void checkmat(float *** mat,float * max,float * min){

Any ideas?

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
Tal Alfi
  • 35
  • 6
  • Because `checkmat`'s `mat` is a pointer-to-pointer-to-pointer, and `main`'s `mat` is a pointer to a 2D array. These have nothing in common. – Quentin May 30 '18 at 13:49

3 Answers3

1

As @Quentin mentioned, there is a difference between the two variables.

float ***

This is a pointer to a pointer to a pointer. I assume you used this because you thought that is how arrays are stored. It's a common misconception that a 2D array is always a array of pointers pointing to arrays.

Rather a pointer to a 2D array should be written as:

float (*)[][height]

In these cases 2D arrays are stored in memory column-after-column (when in column-major mode). Therefore if you have declare a 2D array:

float arr[5][10];

then the following will be true

arr == arr[0]

as the variable 'arr' points to the first element of the 2D array, which is also the start of the first column.

Also, you don't need to create a pointer to the array, as the array variable itself is already a pointer. So, to answer your question, your function parameters are declared incorrectly. It should be:

void checkmat(float mat[M][N],float * max,float * min){...}

NB: You need to specify the array size in the function.

Hein Wessels
  • 937
  • 5
  • 15
0

You do not need any *** pointers

#include <stdio.h>
#include <float.h>

void checkmat(float * mat,float * max,float * min, size_t cols, size_t rows){

    float sum=0,sum2=0,flag=1;

    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            sum+=(mat[i * cols + j]);
            sum2+=(mat[i * cols + j]);
        }
        if(sum > *max)
            *max=sum;
        if(flag){
            *min=sum;
            flag=0;
        }
        if(sum2< *min)
            *min =sum2;
    }
}

int main()
{
   float mat[4][4]={{1,2,3,4},{5,6,7.6,8},{9,1,2.9,3},{4,5,6,7}};
   float min=FLT_MAX,max=-FLT_MAX;

   checkmat((&mat[0][0],&max,&min, sizeof(mat) / sizeof(mat[0]), sizeof(mat[0]) / sizeof(mat[0][0]));

   printf("Size of the matrix is %zu x %zu. %f is max %f is min \n", max, min, sizeof(mat) / sizeof(mat[0]), sizeof(mat[0]) / sizeof(mat[0][0]));

}
0___________
  • 60,014
  • 4
  • 34
  • 74
  • You can't just cast a `float (*)[4]` to a `float *` and expect things to work. – dbush May 30 '18 at 14:09
  • this the array the continues block of memory. it does not matter in this case. The pointer points to the first element of the array (just the type is different). But for you I have changed it – 0___________ May 30 '18 at 14:12
  • You're still treating a 2D array as a 1D array. Declare the function as `void checkmat(float mat[rows][cols] ,float * max,float * min, size_t cols, size_t rows)` and reference it properly in the function, and pass `mat` directly. – dbush May 30 '18 at 14:14
  • @dbush and? It is 100% correct – 0___________ May 30 '18 at 14:53
0

It is often incorrectly said that pointers and arrays are equivalent in C. Your code is an example of this not being the case.

In most contexts, an array will decay to a pointer to its first member. This only applies to the outermost array dimension however. For example, a float [4], which is an array of float, will decay to float *. But a float [4][4], which is an array of float [4] decays into a float (*)[4] (i.e. a pointer to an array of float [4]), not a float **.

In your case you pass &mat, which has type float (*)[4][4], to a function expecting a float ***. These types are not compatible, hence the error.

The proper way to define the function is:

void checkmat(int rows, int cols, float mat[rows][cols] ,float * max,float * min)

This way you pass the 2D array to your function, along with the size of each dimension.

You then use mat in the function like this:

       sum += mat[i][j];
       sum2 += mat[j][i];

And you call the function like this, passing in mat directly instead of its address as well as its dimensions:

checkmat(n,n,mat,&max,&min);
dbush
  • 205,898
  • 23
  • 218
  • 273