1

I'm learning pointers, and gotten stuck for an hour now, with this code,

#include <stdio.h>

int determinant(int **mat)  /* int mat[3][3] works fine.. int *mat[3] doesn't.. neither does int *mat[] */
{
    int det;
    int a=*(*(mat+0)+0); // printf("\n%d",a);
    int b=*(*(mat+0)+1); // printf("\n%d",b);
    int c=*(*(mat+0)+2); // printf("\n%d",c);
    int d=*(*(mat+1)+0); // printf("\n%d",d);
    int e=*(*(mat+1)+1); // printf("\n%d",e);
    int f=*(*(mat+1)+2); // printf("\n%d",f);
    int g=*(*(mat+2)+0); // printf("\n%d",g);
    int h=*(*(mat+2)+1); // printf("\n%d",h);
    int i=*(*(mat+2)+2); // printf("\n%d",i);

    det = a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g);
    return det;
}

int main()
{
    int mat[3][3];
    int i,j;
    printf("Enter the 3 X 3 matrix:\n\n");
    for (i=0;i<3;i++)
    {
        for (j=0;j<3;j++)
        {
            scanf("%d",*(mat+i)+j);
        }
    }
    printf("\nThe determinant of the given 3 X 3 matrix is %d",determinant(mat));
    return 0;
}

I don't think anything is wrong with the function call. Maybe the problem is while accepting the arguments. Idk, isn't mat a pointer to an 1-dimensional array, which would again be a pointer to the array element, making mat a pointer to a pointer? When I print some text at places (just to check), i find that the execution goes till after int det in the function, and the program crashes in the next step. mat [3][3] works well, but i wanna use some * there, because as i said, i'm 'learning'..

Please help! Thanks :)

Shashwat Black
  • 992
  • 5
  • 13
  • 24

5 Answers5

6

The correct prototype for your function is

int determinant(int mat[][3]);

or

int determinant(int (*mat)[3]);

(both are equivalent because of a special rule for arrays as function arguments)

Then you can simply access your matrix elements with something like mat[i][j].

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • http://stackoverflow.com/questions/16943909/manipulate-multidimensional-array-in-a-function – Dchris Jun 05 '13 at 16:04
3

This is because 2 dimensional array and pointer to pointer are not same. No matter how much dimension does an array have, its 1 dimensional in actual memory. So we can access it serially.

    #include <stdio.h>
    #include <conio.h>

    int determinant(int *matrix1stMember)
    {
        int a, b, c, d, e, f, g, h, i;
        a = *(matrix1stMember + 0);
        b = *(matrix1stMember + 1);
        c = *(matrix1stMember + 2);
        d = *(matrix1stMember + 3);
        e = *(matrix1stMember + 4);
        f = *(matrix1stMember + 5);
        g = *(matrix1stMember + 6);
        h = *(matrix1stMember + 7);
        i = *(matrix1stMember + 8);

        return ( a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g) );
    }

    int main()
    {
        int matrix[3][3];    // int matrix[y][x]; not [x][y]
        int i, j;
        printf("\nEnter 3x3 Matrix : ");
        for(j = 0; j < 3; j++)
        {
            for(i = 0; i < 3; i++)
            {
                scanf("%d", &matrix[j][i]);
            }
        }
        // call function determinant(int*) using first member of array
        printf("\nDeterminant = %d", determinant(&matrix[0][0]));
        getch();
        return 0;
    }

If we have to access via row and column then we can do following

    data = *(_1stMemberofArray + rowIndex*totalColumn + columnIndex);

For Example,

    data = matrix[2][1];

where datatype of matrix is

    int matrix[3][3];

is identical to.

    data = *(matrixPointer + 2*3 + 1);

where 3 is total column 2 is row(vertical or y) and 1 is column(horizontal or x). and datatype of matrixPointer is,

    int* matrixPointer; 

and it should point to first member of matrix;

Ankit
  • 39
  • 1
  • http://stackoverflow.com/questions/16943909/manipulate-multidimensional-array-in-a-function – Dchris Jun 05 '13 at 16:03
1

2D array dont decay to pointer to pointer. You can decay them to pointers so your code should look like

int determinant(int *mat) {
  int det;
  int a=*((mat+0)+0); // printf("\n%d",a);
  int b=*((mat+0)+1); // printf("\n%d",b);
  int c=*((mat+0)+2); // printf("\n%d",c);
  int d=*((mat+1*3)+0); // printf("\n%d",d);
  int e=*((mat+1*3)+1); // printf("\n%d",e);
  int f=*((mat+1*3)+2); // printf("\n%d",f);
  int g=*((mat+2*3)+0); // printf("\n%d",g);
  int h=*((mat+2*3)+1); // printf("\n%d",h);
  int i=*((mat+2*3)+2); // printf("\n%d",i);

  det = a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g);
  return det;
}

The above code is just for illustration, showing how 2-D array decays to 1-D array.

When you try to access the array using braces like a[2][1] then compiler does is unfolding for you. By unfolding I mean, the multiplication by sizeof(type) (as shown above multiply by 3). So if you decaying to 1-D you have to do it yourself.

One more thing to add, always pass the size of the dimension to the function who is has to tread the 1-D array as 2-D. like

int determinant(int *mat, int cols, rows);

Edit 1:

Just to add that @JensGustedt ans is also ok if you want to keep the arrays intact across function calls.

havexz
  • 9,550
  • 2
  • 33
  • 29
  • thanks.. now i have a clear concept.. :) – Shashwat Black Dec 28 '11 at 18:39
  • 2
    -1. This is simply not an adequat solution. C knows very well how to handle 2D arrays and how to pass them as arguments. You just have to get the syntax right. – Jens Gustedt Dec 28 '11 at 18:42
  • @JensGustedt I understand your ans but if you want to decay your 2D array to pointer then this is the way. If you want to keep arrays as is then its your way...because `int determinant(int mat[3][3])` will work too. But he said he is learning pointers...;) – havexz Dec 28 '11 at 18:52
  • An array always decays to a pointer for a function argument, in that case to a pointer to a three dimensional array, namely `int (*mat)[3]`. From what I see in his comment, this was just the syntax that s/he was missing. – Jens Gustedt Dec 28 '11 at 19:01
  • `I'm learning pointers` so i thought its about pointers. Well true arrays decay to pointers but pointer arithmetic depends upon how you declare function prototype for array. If you use array notation then compiler will do the array arithmetic for you (you can use `arr[i][j]` notation in function) and if you decay to normal pointer you hv to do pointer arithmetic yourself. – havexz Dec 28 '11 at 22:08
  • http://stackoverflow.com/questions/16943909/manipulate-multidimensional-array-in-a-function – Dchris Jun 05 '13 at 16:03
1

The correct signature for the function would be

int determinant(int mat[][3])

or

int determinant(int (*mat)[3])

In the context of a function parameter declaration, T a[] and T *a are exactly equivalent.

With either option, you can subscript mat normally in the function as you would in main:

int a = mat[0][0];
int b = mat[0][1];
...

Since a subscript operation implicitly dereferences the pointer (a[i] == *(a + i)), you don't have to do the explicit dereference dance, making your code easier to read and understand (and potentially faster; I've seen some compilers generate more instructions for *(*(a + i) + j) than a[i][j], but don't rely on that being true everywhere).

Remember that when an expression of "N-element array of T" appears in most contexts, it is converted to an expression of type "pointer to T" and its value is the address of the first element in the array. Since the expression mat in the call to printf has type "3-element array of 3-element arrays of int", it is replaced with an expression of type "pointer to 3-element array of int".

John Bode
  • 119,563
  • 19
  • 122
  • 198
0

If we pass a multidimensional array to a function:

int a2[5][7];
func(a2);

We can not declare that function as accepting a pointer-to-pointer

func(int **a)           /* WRONG */
{
...
}

The function ends up receiving a pointer-to-an-array, not a pointer-to-a-pointer.

Sangeeth Saravanaraj
  • 16,027
  • 21
  • 69
  • 98