Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incompatible pointer types and constness

Tags:

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?

like image 212
Julien Thierry Avatar asked Feb 24 '15 16:02

Julien Thierry


2 Answers

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.

like image 100
n. 1.8e9-where's-my-share m. Avatar answered Nov 14 '22 04:11

n. 1.8e9-where's-my-share m.


From the C-FAQ [Question 11.10]

In C, if you must assign or pass pointers which have qualifier mismatches at other than the first level of indirection, you must use explicit casts (e.g. (const char **) in this case), although as always, the need for such a cast may indicate a deeper problem which the cast doesn't really fix.

In your case:

test_function((const char (*)[3])my_var);
like image 6
David Ranieri Avatar answered Nov 14 '22 04:11

David Ranieri