views:

93

answers:

3

I want to scan a 2D array with the help of pointers and have written this code, could you tell me why the compiler gives errors? I know how to use double pointers to do the same, i was experimenting with this one.

#include<stdio.h>
#include<stdlib.h>
int main(void) {
    int i,j,n,a,b;
    int (*(*p)[])[];
    printf("\n\tEnter the size of the matrix in the form aXb\t\n");
    scanf("%dX%d",&a,&b);
    p=(int (*(*p)[b])[a])malloc(b*sizeof(int (*p)[a]));
    for(i=0;i<b;i++) {
            p[i]=(int (*p)[a])malloc(a*sizeof(int));
            printf("\t\bEnter Column %d\t\n");
            for(j=0;j<a;j++)
                    scanf("%d",&p[i][j]);
    }
    return 0;
}
+1  A: 

You are using pointers to arrays, so you shouldn't index them directly, as p[i] will give *(p+i) i.e. an array following the one pointed to by p, rather than an element of p.

In C, void* will convert to any pointer type, so you don't need to cast the result of malloc. If you do put the casts in, it can mask errors, for example if you are trying to assign to a non-pointer ( such as p[i] ).

In the malloc for p, sizeof(int (*p)[a]) should either use a type or an expression, not a declaration. p is a pointer to an array of pointers to arrays of int, so the type of the elements of *p is int (*)[].

So this compiles without error or warning on gcc:

#include<stdio.h>
#include<stdlib.h>
int main ( void )
{
    int i, j, n, a, b;

    int ( * ( * p ) [] ) [];

    printf ( "\n\tEnter the size of the matrix in the form aXb\t\n" );

    scanf ( "%dX%d", &a, &b );

    p = malloc ( b * sizeof ( int ( * ) [] ) );

    for ( i = 0;i < b;i++ ) {
        ( *p ) [i] = malloc ( a * sizeof ( int ) );
        printf ( "\t\bEnter Column %d\t\n", i );
        for ( j = 0;j < a;j++ )
            scanf ( "%d", & ( * ( *p ) [i] ) [j] );
    }


    return 0;
}

However, since there is no advantage in using a pointer to an array against using a pointer to its first element but it does mean you have to dereference before taking the element, it is much easier to use the pointer to a pointer form.

Pete Kirkham
This is a brilliant answer. Thank you! :)
n0nChun
+1  A: 

Do you know what int (*(*p)[])[] is?
Try cdecl.org ... http://cdecl.ridiculousfish.com/?q=int+%28%2A%28%2Ap%29%5B%5D%29%5B%5D

To use a 1-dimensional array and pretend it's a 2-dimensional one

  1. declare a 1-dimensional object (pointer, array, whatever)
  2. malloc a rectangular size
  3. compute linear addressing value based on row, column, and column size
  4. use it
  5. free the array

That's it

/* Oh ... and use spaces in your code */
/* They are extremely cheap now a days */
#include <assert.h>
/* instead of asserting malloc and scanf, use proper error checking */
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int i, j, n, rows, cols;
    int *p;                                            /* 1. */

    printf("Enter the size of the matrix in the form aXb\n");
    n = scanf("%dX%d", &rows, &cols);
    assert((n == 2) && ("scanf failed"));
    p = malloc(rows * cols * sizeof *p);               /* 2. */
    assert((p != NULL) && "malloc failed");
    for (i = 0; i < rows; i++) {
            int rowindex = i * cols;                   /* 3. */
            for (j = 0; j < cols; j++) {
                    n = scanf("%d", &p[rowindex + j]); /* 3. and 4. */
                    assert((n == 1) && "scanf failed");
            }
    }
    free(p);                                           /* 5. */
    return 0;
}
pmg
A: 

You are unnecessarily complicating the problem of accessing array elements using pointers. Try to use a simple pointer-to-pointer p.

int **p;
...
p=malloc(a*sizeof(int *));   //create one pointer for each row of matrix
...
for(i=0;i<a;i++)
{
...
p[i]=malloc(b*sizeof(int));  //create b integers in each row of matrix
...
}
Kedar Soparkar
You might want to "use" the object (rather than the type) as argument to the sizeof operator. If you change p to `double **p` in the future, you won't need to change the lines with mallocs `p = malloc(a * sizeof *p);` and `p[i] = malloc(b * sizeof *p[i]);`
pmg
Kedar Soparkar