user7341005
user7341005

Reputation: 285

incompatible pointer types passing int[5][5] to parameter of type int**

why this error(picture 1) happened when I want to input a 2d array to a function?

enter image description here

#include <stdio.h>
#include <stdlib.h>
void pr(int** a){
    printf("%d", a[0][0]);
}

int main(){
    int a[5][5]={{1,4,7,11,15},{2,5,8,12,19},{3,6,9,16,22},{10,13,14,17,24},{18,21,23,26,30}};
    pr(a);
}

Upvotes: 3

Views: 13319

Answers (2)

ilim
ilim

Reputation: 4547

Arrays and pointers can not be used interchangeably in all possible use cases, and you just happened to stumble into one of them. At times, an int array can be implicitly converted into a pointer, and at times it, well, shouldn't be.

In your case, implicitly (or explicitly) converting a to an (int **) would not work, simply because a points to the first element in your 2d array when considered as a pointer. Converting a to an int ** would make pr lose the information on a being an array. Consequently, handling it as a typical (int **) in pr and trying to dereference it twice would cause the first element in a (a[0][0] = 1) to be handled as an address and the value in that address would be looked up, which I believe is not the desired behavior of pr().

Ideally, you should declare pr in a way that takes a 2D array as a parameter, not an int **. A declaration of pr with the mentioned fix is given below.

void pr(int a[][5]){
    printf("%d", a[0][0]);
}

Now, you mention in the comments to your question that the definition of pr can not be modified. In order not to modify pr(), you would have to change the data structure you have in main to something similar to the one given below.

int main(){
    int a0[5]={1,4,7,11,15};
    int a1[5]={2,5,8,12,19};
    int a2[5]={3,6,9,16,22};
    int a3[5]={10,13,14,17,24};
    int a4[5]={18,21,23,26,30};
    int *a[5] = {a0, a1, a2, a3, a4};
    pr(a);
}

Note that the sample above is not the most syntactically concise way to achieve your goal. Also, check here to see this usage at work.

Upvotes: 5

Jonathan Leffler
Jonathan Leffler

Reputation: 753970

The core problem is that arrays and pointers are not the same (albeit they are closely related), and a 2D array is not an array of pointers.

This code shows three ways to fix up the problem. The array a0 is your array renamed and reformatted; the array a is an array of pointers, and each pointer is a pointer to an array of 5 int via a 'compound literal', a feature added to C99. I've upgraded the printing function to print all 25 elements of the array that is passed to it — and created two new printing functions with different interfaces that also print the entire array passed to them. I assume the array is square; a rectangular (non-square) matrix can be readily handled, especially by a variant on pr1() such as pr2(int n, int m, int a[n][m]) — which is almost identical to pr1() but needs a single adjustment internally to test j against m instead of n.

#include <stdio.h>

static void pr0(int a[][5]);
static void pr1(int n, int a[n][n]);

static void pr(int **a)
{
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
            printf("%3d", a[i][j]);
        putchar('\n');
    }
    putchar('\n');
}

int main(void)
{
    int a0[5][5] =
    {
        {  1,  4,  7, 11, 15 },
        {  2,  5,  8, 12, 19 },
        {  3,  6,  9, 16, 22 },
        { 10, 13, 14, 17, 24 },
        { 18, 21, 23, 26, 30 },
    };
    int *a[] =
    {
        (int[]){  1,  4,  7, 11, 15 },
        (int[]){  2,  5,  8, 12, 19 },
        (int[]){  3,  6,  9, 16, 22 },
        (int[]){ 10, 13, 14, 17, 24 },
        (int[]){ 18, 21, 23, 26, 30 },
    };

    pr(a);
    pr0(a0);
    pr1(5, a0);

    return 0;
}

static void pr0(int a[][5])
{
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
            printf("%3d", a[i][j]);
        putchar('\n');
    }
    putchar('\n');
}

static void pr1(int n, int a[n][n])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            printf("%3d", a[i][j]);
        putchar('\n');
    }
    putchar('\n');
}

The sample output is wonderfully uniform:

  1  4  7 11 15
  2  5  8 12 19
  3  6  9 16 22
 10 13 14 17 24
 18 21 23 26 30

  1  4  7 11 15
  2  5  8 12 19
  3  6  9 16 22
 10 13 14 17 24
 18 21 23 26 30

  1  4  7 11 15
  2  5  8 12 19
  3  6  9 16 22
 10 13 14 17 24
 18 21 23 26 30

The three blocks are the same. Given a choice, I'd use the technique in pr1(), using VLAs (variable length arrays) in the interface. If you must stick with the int ** argument, you must stick with the array a, or something quite similar. There are certainly other ways to create that. For example:

int *a[] = { a0[0], a0[1], a0[2], a0[3], a0[4] };

Upvotes: 7

Related Questions