2016-12-16 145 views
4

当我使用GCC 4.9.2编译下面的程序时,我得到以下警告:从不兼容的指针类型传递'P'的参数1。但是,我没有看到该计划有任何问题。任何线索?GCC发出不兼容指针类型的警告

typedef int Row[10]; 

void P(const Row A[]) 
{ 
} 


int main(void) 
{ 
    Row A[10]; 

    P(A); 
    return 0; 
} 

下面是完整的输出从GCC标准错误:

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[]) 
    ^

编辑:程序锵3.5.0选项-pedantic -std=c89 -Wall完全编译。

+2

你怎么看待'const'预选赛什么? –

+0

@SouravGhosh我认为它承诺调用者参数* A *不会改变。 –

+0

是的,所以,功能期望.......? –

回答

4

摆脱的typedef,它应该成为一点点清晰的:

void P (const int A [][10]) 
{ 
} 

int main(void) 
{ 
    int A[10][10]; 

    P(A); 
    return 0; 
} 

的问题是,在函数参数数组“衰变”到const int(*) [10]类型的指针,这是指向项目为const的数组的指针。

该指针类型与您从main传递的内容不兼容,因为该数组衰减到类型为int(*)[10]的数组指针。

有一个“指针类型可以转换为限定指针类型”的规则。例如,int*的含义可以转换为const int*,但不是相反。但是这个规则在这里不适用。

因为“pointer-to-array”的限定版本是“const-pointer-to-array”,而不是“pointer-to-const-array”,这就是你在这里的内容。

不幸的是,这是C语言的一个弱点:在使用数组指针时,你不能拥有const正确性。唯一的解决方案是一个非常丑陋的:

P((const int(*)[10]) A); 

这样的情况下完全跳过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; 
} 
+0

不需要将'const'传递给具有'const'参数的函数。函数中的'const'只是表示参数不会在函数中被修改。参见例如'strcmp'功能。 –

+0

该程序与Clang 3.5.0用选项'-pedantic -std = c89 -Wall'干净地编译。这是否意味着Clang中存在一个错误? –

+2

@RishikeshRaje请再次阅读我的答案,我明确表达了你的意思,这里不适用。 – Lundin

-1

根据错误消息函数期望一个指向常量的指针。

typedef int Row[10]; 

void P(const Row A[]) 
{ 
} 


int main(void) 
{ 
    const Row A[10]; 

    P(A); 
    return 0; 
} 
+0

我认为“当参数定义(const Row A [])的一部分仅在函数P的作用域内适用时,则为“const”。 – cdcdcd

+1

这不回答问题。如果数组不是“const”,但OP仅仅需要const正确性,这很可能是这种情况。 – Lundin