GCC issues warning of incompatible pointer type

1.9k views Asked by At

When I compile the program below with GCC 4.9.2 I get the following warning: passing argument 1 of ‘P’ from incompatible pointer type. However, I don't see anything wrong with the program. Any clues?

typedef int Row[10];

void P(const Row A[])
{
}


int main(void)
{
    Row A[10];

    P(A);
    return 0;
}

Here is the complete output from GCC to stderr:

test.c: In function ‘main’:
test.c:12:4: warning: passing argument 1 of ‘P’ from incompatible pointer type
  P(A);
    ^
test.c:3:6: note: expected ‘const int (*)[10]’ but argument is of type ‘int (*)[10]’
 void P(const Row A[])
      ^

Edit: The program compiles cleanly with Clang 3.5.0 and the options -pedantic -std=c89 -Wall.

1

There are 1 answers

5
Lundin On BEST ANSWER

Get rid of the typedef and it should become a little bit clearer:

void P (const int A [][10])
{
}

int main(void)
{
    int A[10][10];

    P(A);
    return 0;
}

The problem is that the array in the function parameter "decays" into a pointer of type const int(*) [10], which is a pointer to an array where the items are const.

This pointer type is not compatible with what you pass from main, because that array decays into an array pointer of type int(*)[10].

There is a rule of "pointer-to-type may be converted to qualified-pointer-to-type". Meaning for example int* may be converted to const int* but not the other way around. But that rule does not apply here.

Because the qualified version of "pointer-to-array" is "const-pointer-to-array", and not "pointer-to-const-array", which is what you have here.

Unfortunately this is a weakness in the C language: you cannot have const correctness while using array pointers. The only solution is a very ugly one:

P( (const int(*)[10]) A);

It might be better to skip const correctness completely for cases like this, in favour of readability.


Edit: In C11 you can do like this, which is more type safe but it still relies on the caller performing a cast:

#define const_array_cast(arr, n) _Generic(arr, int(*)[n] : (const int(*)[n])arr )

void P (const int A [][10])
{
}


int main(void)
{
    int A[10][10];

    P(const_array_cast(A,10));
    return 0;
}