将二维数组传递给常量参数的函数

时间:2015-01-21 07:53:19

标签: c arrays pointers gcc-warning

我从 C Primer Plus 学到如果你想保护一个数组不被一个函数意外修改,你应该在函数头中的指针声明之前添加const修饰符定义

遵循这个明智的建议,在下面的最小例子中,我试图将一个非常数二维数组array传递给函数Sum2D,其中一个参数是{{ 1}}。

pointer-to-const-int[2]

但是,#include <stdio.h> #define ROWS 2 #define COLS 2 int Sum2D(const int ar[][COLS], int rows); //use `const` to protect input array int main(void) { int array[ROWS][COLS]={{1,2},{3,4}}; //the non-constant array printf( "%d\n", Sum2D(array,ROWS) ); return 0; } int Sum2D(const int ar[][COLS], int rows) { int total=0; int i,j; for( i=0 ; i<rows ; i++ ) { for( j=0 ; j<COLS ; j++ ) { total+=ar[i][j]; } } return total; } 无法在不发出以下警告的情况下成功编译此代码:

gcc

1)为什么要警告?

2)如何消除“噪音”?(除了将$gcc -ggdb3 -Wall -Wextra -o test test.c test.c: In function ‘main’: test.c:16:2: warning: passing argument 1 of ‘Sum2D’ from incompatible pointer type [enabled by default] printf( "%d\n", Sum2D(array,4) ); ^ test.c:4:5: note: expected ‘const int (*)[4]’ but argument is of type ‘int (*)[4]’ int Sum2D(const int ar[][COLS], int rows); ^ 添加到const声明之外。)

(如果array和函数都使用一维数组,则没有警告。)

  

系统信息:

     

Ubuntu 14.04LTS

     

编译器:gcc 4.8.2

2 个答案:

答案 0 :(得分:9)

这是一个不幸的错误&#34;在C&C的设计中; T (*p)[N]不会隐式转换为T const (*p)[N]。您必须使用丑陋的强制转换,或者让函数参数不接受const


乍一看,这种转换看起来应该是合法的。 C11 6.3.2.3/2:

  

对于任何限定符 q ,指向非 q - 限定类型的指针可能会转换为指向 q - 限定的指针版型;

然而,还要看C11 6.7.3 / 9(C99中是/ 8):

  

如果数组类型的规范包含任何类型限定符,则元素类型是限定的,而不是数组类型。

最后一句话说,int const[4] 被认为是const - int[4]的合格版本。实际上它是一个非const限定的4 const int个数组。 int[4]int const[4]是不同元素类型的数组。

因此,6.3.2.3/2实际上不允许int (*)[4]转换为int const (*)[4]


const和数组出现此问题的另一个奇怪的情况是当typedef正在使用时;例如:

typedef int X[5];
void func1( X const x );
void func1( int const x[5] );

这会导致编译器错误:X const x表示x是const,但它指向的是非const int的数组;而int const x[5]表示x不是const,而是指向一个const int数组!

进一步阅读here,感谢@JensGustedt

答案 1 :(得分:0)

您可以在调用函数时键入强制转换数组。它不会自动将非const转换为const。 你可以用它。

Sum2D( (const int (*)[])array, ROWS );