Home > front end >  How to pass a multidimensional array to a C function using pointers?
How to pass a multidimensional array to a C function using pointers?

Time:07-15

I'm trying to write a program where you have to find the maximum and minimum number in a multidimensional array using double pointers. But when I try to compile it, the compiler returns to me this message:

warning: passing argument 1 of 'MinMax' from incompatible pointer type [-Wincompatible-pointer-types]
   33 |     MinMax(V, ptm, ptM);
      |            ^
      |            |
      |            double (*)[5]

.\1-maxminarraymulti.c:18:22: note: expected 'double **' but argument is of type 'double (*)[5]'
   18 | void MinMax(double **V, double **mi, double **Ma);".

Code:

#include <stdio.h>

#define N 5
#define M 5

void MinMax(double **V, double **mi, double **Ma);

void main() {
    double V[N][M] = { { 1, 5, 2, 3, 9 },
                       { 12, 6, 90, 2, 0 },
                       { -12, 41, 2, 9, 56 },
                       { 78, 2, 1, 523, 39 }, 
                       { 92, 13, 63, 2, 12 } };

    double Min, Max;

    double *ptMin = &Min;
    double *ptMax = &Max;

    double **ptm = &ptMin;
    double **ptM = &ptMax;
    
    MinMax(V, ptm, ptM);
}

void MinMax(double **V, double **mi, double **Ma) {
    
    //printf to see if the bi-dimensional array has been passed correctly to function.
    printf("%lf", V[3][0]);
}

CodePudding user response:

The prototype for your function should be different: it should take a matrix of N by M doubles and pointers to double for the results. The matrix should be const qualified since the function does not modify it.

You could write this as:

void MinMax(double const V[N][M], double *minp, double *maxp);

This prototype is somewhat confusing because arrays are not passed by value: they decay as pointers to their first element, so the array V defined as double V[N][M] is passed to MinMax as a pointer to its first element, a pointer to arrays of M double with type double (*V)[M]. This conversion is implicit and the function prototype applies is implicitly as well, leading to surprising results such as `sizeof(V) == sizeof(double (*)[M]), which is the size of a pointer, not the size of the array, nevertheless that on the matrix. The above definition is equivalent to:

void MinMax(double const (*V)[M], double *minp, double *maxp);

or

void MinMax(double const V[][M], double *minp, double *maxp);

Note that neither of the above prototypes specify the number of rows in the matrix, hence the function can be called with matrices of any number of rows. Either the number is a convention, as double const V[N][M] may imply, or the actual number can be passed as an argument:

void MinMax(int rows, double const V[][M], double *minp, double *maxp);

Unlike previous versions where the second and subsequent dimentions must be known at compile time, C99 allows the matrix size to be specified as variables:

void MinMax(int rows, int cols, double const V[rows][cols],
            double *minp, double *maxp);

Which is still equivalent to:

void MinMax(int rows, int cols, double const V[][cols],
            double *minp, double *maxp);

and

void MinMax(int rows, int cols, double const (*V)[cols],
            double *minp, double *maxp);

Here is a modified version with an C89 implementation of MinMax for a fixed matrix size:

#include <stdio.h>

#define N 5
#define M 5

void MinMax(double const V[N][M], double *minp, double *maxp);

int main() {
    double V[N][M] = { { 1, 5, 2, 3, 9 },
                       { 12, 6, 90, 2, 0 },
                       { -12, 41, 2, 9, 56 },
                       { 78, 2, 1, 523, 39 }, 
                       { 92, 13, 63, 2, 12 } };
    double Min, Max;
    
    MinMax(V, &Min, &Max);
    printf("min=%g, max=%g\n", Min, Max);
    return 0;
}

void MinMax(double const V[N][M], double *minp, double *maxp) {
    double min = V[0][0];
    double max = V[0][0];
    for (int i = 0; i < N; i  ) {
        for (int j = 0; j < M; j  ) {
            if (min > V[i][j])
                min = V[i][j];
            if (max < V[i][j])
                max = V[i][j];
        }
    }
    *minp = min;
    *maxp = max;
}

Output:

min=-12, max=523

Here is a C99 version where the matrix size is specified dynamically:

#include <stdio.h>

void MinMax(int N, int M, double const V[N][M],
            double *minp, double *maxp);

int main() {
    double V[][5] = { { 1, 5, 2, 3, 9 },
                      { 12, 6, 90, 2, 0 },
                      { -12, 41, 2, 9, 56 },
                      { 78, 2, 1, 523, 39 }, 
                      { 92, 13, 63, 2, 12 } };
    double Min, Max;
    int rows = sizeof(V) / sizeof(V[0]);
    int cols = sizeof(V[0]) / sizeof(V[0][0]);
    
    MinMax(rows, cols, V, &Min, &Max);
    printf("min=%g, max=%g\n", Min, Max);
    return 0;
}

void MinMax(int N, int M, double const V[N][M],
            double *minp, double *maxp) {
    double min = V[0][0];
    double max = V[0][0];
    for (int i = 0; i < N; i  ) {
        for (int j = 0; j < M; j  ) {
            if (min > V[i][j])
                min = V[i][j];
            if (max < V[i][j])
                max = V[i][j];
        }
    }
    *minp = min;
    *maxp = max;
}

Output:

min=-12, max=523

To handle arbitrary large matrices, rows, cols, i and j should be defined with type size_t

Note that for this problem, you could just consider the matrix as an array of rows * cols double and pass the count of elements and a pointer to the first element of the first row, an approach that does not require C99 VLA syntax:

#include <stdio.h>

void MinMax(size_t count, double const *V, double *minp, double *maxp);

int main() {
    double V[][5] = { { 1, 5, 2, 3, 9 },
                      { 12, 6, 90, 2, 0 },
                      { -12, 41, 2, 9, 56 },
                      { 78, 2, 1, 523, 39 },
                      { 92, 13, 63, 2, 12 } };
    double Min, Max;
    int rows = sizeof(V) / sizeof(V[0]);
    int cols = sizeof(V[0]) / sizeof(V[0][0]);

    MinMax(rows * cols, &V[0][0], &Min, &Max);
    printf("min=%g, max=%g\n", Min, Max);
    return 0;
}

void MinMax(size_t count, double const *V, double *minp, double *maxp) {
    double min = V[0];
    double max = V[0];
    for (size_t i = 0; i < count; i  ) {
        if (min > V[i])
            min = V[i];
        if (max < V[i])
            max = V[i];
    }
    *minp = min;
    *maxp = max;
}

Output:

min=-12, max=523

CodePudding user response:

I would use VLAs - you can pass any size array, not only with defined compile time sizes

The function assumes that you want to get pointers to cells holding max and min value

void MinMax(const size_t rows, const size_t cols, const double (*V)[cols], const double **minp, const double **maxp) 
{
    *minp = &V[0][0];
    *maxp = &V[0][0];
    for (size_t row = 0; row < rows; row  ) 
    {
        for (size_t col = 0; col < cols; col  ) 
        {
            *minp = V[row][col] < **minp ? &V[row][col] : *minp;
            *maxp = V[row][col] > **maxp ? &V[row][col] : *maxp;
        }
    }
}

VLAs are optional feature but will be not soon :)

  • Related