当我用GCC 4.9.2编译下面的程序时,我得到以下警告:从不兼容的指针类型传递'P'的参数1.但是,我没有看到该程序有任何问题.有线索吗?
typedef int Row[10];
void P(const Row A[])
{
}
int main(void)
{
Row A[10];
P(A);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
以下是GCC到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[])
^
Run Code Online (Sandbox Code Playgroud)
编辑:该程序与Clang 3.5.0和选项完全编译-pedantic -std=c89 -Wall
.
摆脱typedef,它应该变得更加清晰:
void P (const int A [][10])
{
}
int main(void)
{
int A[10][10];
P(A);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
问题是函数参数中的数组"衰减"为类型的指针const int(*) [10]
,这是指向项目所在的数组的指针const
.
此指针类型与从main传递的内容不兼容,因为该数组会衰减为类型的数组指针int(*)[10]
.
有一个规则"指向类型的指针可以转换为限定指针到类型".例如,int*
可以转换为const int*
但不是相反的含义.但是这条规则不适用于此.
因为"指向数组的指针"的限定版本是"const-pointer-to-array",而不是"指向const-array"指针,这就是你在这里所拥有的.
不幸的是,这是C语言的一个弱点:使用数组指针时,不能有const正确性.唯一的解决方案是非常难看的:
P( (const int(*)[10]) A);
Run Code Online (Sandbox Code Playgroud)
对于这样的情况,最好完全跳过const正确性,这有利于可读性.
编辑:在C11中你可以这样做,这更安全,但仍然依赖于执行转换的调用者:
#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;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
711 次 |
最近记录: |