0

I have a basic question related to indexing 2d arrays passed to a function in C. When I use a double pointer to pass it:

  • Inside the function printMatrix indexing A as A[i][j] works if memory for A in main was allocated using malloc
  • Inside the function printMatrix indexing A as A[i][j] doesn't work if memory for A in main was allocated statically (as in the commented code). I believe I should use: *(*(A+i*N)+j) but why doesn't A[i][j] work when it works for the case above?

void printMatrix(int** A,int N) {
    int i=0,j=0;
    for(i=0;i<N;i++) {
        for(j=0;j<N;j++) {
            printf("%2d",A[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    return;
}

int main() {
    //int A[6][6] = {{1,1,1,1,1,1},{2,2,2,2,2,2},{3,3,3,3,3,3},
    //{4,4,4,4,4,4},{5,5,5,5,5,5},{6,6,6,6,6,6}};
    int N = 6,i,j;
    int **A = (int**)malloc(sizeof(int*)*N);
    for(i=0;i<N;i++)
        A[i] = (int*)malloc(sizeof(int)*N);

    for(i=0;i<N;i++) 
        for(j=0;j<N;j++)
            A[i][j] = i+j;

    printMatrix((int**)A,N);
    return 0;
}
autistic
  • 1
  • 3
  • 35
  • 80
Vandana
  • 127
  • 1
  • 1
  • 10
  • 3
    If you have `int A[6][6]`, then passing it to a function does not give you an `int **` argument. You have a true array, not an array of pointers to arrays of `int`. The compiler told you about it; that's presumably why you have the bludgeon `(int **)A` cast in the call to `printMatrix()`. The cast says "I know better than the compiler"; that's not a good idea when you don't. – Jonathan Leffler Jan 30 '16 at 05:26

1 Answers1

1

Taking an analytical viewpoint, if we declare an array with automatic storage duration in main, such as:

int A[6][6];

We can measure the size of this allocation by using sizeof A, and this will be equal to sizeof (int) * 6 * 6.

In the following code, however, you are allocating sizeof (int *) * 6 + sizeof (int) * 6 * 6 bytes:

int N = 6,i,j;
int **A = (int**)malloc(sizeof(int*)*N);
for(i=0;i<N;i++)
    A[i] = (int*)malloc(sizeof(int)*N);

This should indicate a flaw in your understanding of arrays, and you're doing too much work. For a start, an array is a single continuous block of memory, while what you're allocating is not. You're calling malloc too many times, and allocating too many bytes.

If you continue to sharpen your axe by learning more about C, you'll learn neat tricks such as achieving your goal with one allocation, allocating the same number of bytes, and with one line of code:

int (*A)[N] = malloc(N * sizeof *A);

You'll probably want to adjust the type of print_matrix to reflect the change of A as follows:

void printMatrix(size_t N, int (*A)[N])

P.S. Don't cast malloc

P.P.S. Check malloc for NULL return values.

P.P.P.S. There are two meanings for "static" in C, and neither of them are what you think they are...

Community
  • 1
  • 1
autistic
  • 1
  • 3
  • 35
  • 80
  • :) Thank you Seb. I love your P.S's. Can you explain a bit more on what int (*A)[N] = malloc(N * sizeof *A); does? What can such arrays be called - statically initialized or compile-time available arrays? – Vandana Jan 30 '16 at 06:07
  • Can you also answer as to why (a) works and (b) doesn't? – Vandana Jan 30 '16 at 06:09
  • @Vandana I mostly have, by writing "an array is a single continuous block of memory, while what you're allocating is not". – autistic Jan 30 '16 at 06:17
  • @Vandana You need to realise why your compiler is warning you when you remove the cast from `printMatrix((int**)A,N);`... It's because the underlying allocations are different, and the type reflects that the underlying allocations are different. Different type, different representation, and you get a warning. – autistic Jan 30 '16 at 06:21
  • For sure, I could write an entire chapter of a book on the types in C and how and when they convert... but that is something your book should cover. If you have to ask for further details on this, it's probably because your book isn't working for you. – autistic Jan 30 '16 at 06:24