不兼容的指针类型和常量

我有一个函数采用静态二维数组并将数组元素的元素视为常量:

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

我试着调用如下函数:

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

使用gcc编译(没有任何标志)时,我收到以下警告:

 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]); 

如果我从test_function的原型中删除const ,警告就会消失。 但它并不是我想要的。

当使用clang同时编译-pedantic-errors-Wall我没有得到关于指针不兼容性的任何警告。

我只是想了解为什么gcc在这种情况下输出这样的警告。 为什么我的指针/数组不兼容?

海湾合作委员会对标准的字母是正确的,而且Clang是错误的。

6.3.2.3/2:

对于任何限定符q ,指向非q限定类型的指针可以转换为指向该类型的q限定版本的指针;

看起来很有希望。 但坚持下去。

6.2.5 / 26:

派生类型不是由派生类型的限定符(如果有)限定的

专用于arrays的标准的这种规定不是必需的,并且可以容易地逆转。 也就是说, const char[3]可以很容易地成为const char[3]的const限定版本。 但事实并非如此。 它们只是不同的,不兼容的类型。 事实上,C中根本没有const限定的数组类型,所以你不能拥有char[3]的const限定版本。 这是我们必须遵守的标准。

来自C-FAQ [ 问题11.10 ]

在C中,如果必须分配或传递在第一级间接之外具有限定符不匹配的指针,则必须使用显式强制类型转换(例如,在这种情况下为(const char **)),尽管一如既往需要这样的演员可能表示演员没有真正解决的更深层次的问题。

在你的情况下:

 test_function((const char (*)[3])my_var);