我从 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
答案 0 :(得分:9)
这是一个不幸的错误&#34;在C&C的设计中; T (*p)[N]
不会隐式转换为T const (*p)[N]
。您必须使用丑陋的强制转换,或者让函数参数不接受const
。
对于任何限定符 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 );