不兼容的指针类型和常量

Jul*_*rry 17 c pointers

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

void test_function(const char arr[3][3]);
Run Code Online (Sandbox Code Playgroud)

我试图调用如下函数:

char my_var[3][3] = { {0, 0, 0}, {0, 0, 0}, {0, 0, 0} };
test_function(my_var);
Run Code Online (Sandbox Code Playgroud)

使用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]);
Run Code Online (Sandbox Code Playgroud)

如果我删除了consttest_function的原型,警告消失.但它并不是我想要的.

用clang编译两者时-pedantic-errors,-Wall我没有得到任何关于指针不兼容的警告.

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

n. *_* m. 11

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

6.3.2.3/2:

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

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

6.2.5/26:

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

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

  • 因为`const char [3]`作为函数参数是谎言.它被默默地视为`const char*`.实际参数被衰减为`char*`.然后整个业务由我引用的6.3.2.3/2涵盖. (5认同)

Dav*_*eri 6

来自C-FAQ [ 问题11.10 ]

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

在你的情况下:

test_function((const char (*)[3])my_var);
Run Code Online (Sandbox Code Playgroud)