C – Incompatible Pointer Types and Constness Explained

c++pointers

I have a function taking a static two-dimensional array and treating the elements of the elements of the array as being constant:

void test_function(const char arr[3][3]);

I am trying to call such a function as follows:

char my_var[3][3] = { {0, 0, 0}, {0, 0, 0}, {0, 0, 0} };
test_function(my_var);

When compiling with gcc (without any flag), I get the following warning:

test.c:9:8: warning: passing argument 1 of 'test_function' from incompatible pointer type
   test_function(my_var);
                 ^
test.c:4:6: note: expected 'const char (*)[3]' but argument is of type 'char (*)[3]'
 void test_function(const char arr[3][3]);

If I remove the const from test_function's prototype, the warning goes away. But it is not really what I want.

When compiling with clang with both -pedantic-errors and -Wall I don't get any warning about pointer incompatibility.

I just would like to understand why gcc outputs such a warning in this case.
Why would my pointers/arrays be incompatible?

Best Answer

GCC is right to the letter of the standard and Clang is wrong.

6.3.2.3/2:

For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type;

Looks very promising. But hold on.

6.2.5/26:

A derived type is not qualified by the qualifiers (if any) of the type from which it is derived

This provision of the standard as applied specifically to arrays is not necessary, and could be easily reversed. That is, const char[3] could be easily made a const-qualified version of char[3]. But it is not. They are just different, incompatible types. In fact there are no const-qualified array types in C at all, so you can't have a const-qualified version of char[3]. That's the standard we have and must live with.

Related Question