将二维数组传递给常量参数的函数 [英] Pass a two dimensional array to a function of constant parameter
问题描述
我从C Primer Plus 中了解到,如果您想保护数组不被函数意外修改,您应该在指针声明之前添加 const
修饰符函数定义的头部.
遵循这个明智的建议,在下面的最小示例中,我试图将一个非常量二维数组 array
传递给函数 Sum2D
,一个参数其中是一个pointer-to-const-int[2]
.
#include #define 行 2#define COLS 2int Sum2D(const int ar[][COLS], int 行);//使用`const`来保护输入数组int main(void){int array[ROWS][COLS]={{1,2},{3,4}};//非常量数组printf( "%d\n", Sum2D(array,ROWS));返回0;}int Sum2D(const int ar[][COLS], int 行){整数总计=0;int i,j;for( i=0 ; i
然而,gcc
无法成功编译此代码而不发出以下警告:
$gcc -ggdb3 -Wall -Wextra -o test test.ctest.c:在函数‘main’中:test.c:16:2: 警告:从不兼容的指针类型传递Sum2D"的参数 1 [默认启用]printf( "%d\n", Sum2D(array,4));^test.c:4:5:注意:应为const int (*)[4]",但参数的类型为int (*)[4]"int Sum2D(const int ar[][COLS], int 行);^
1) 为什么会出现警告?
2) 如何消除噪音"?(除了将 const
添加到 array
声明.)
(如果array
和函数都使用一维数组,则没有警告.)
系统信息:
Ubuntu 14.04LTS
编译器:gcc 4.8.2
这是 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]
不是被认为是int[的
.实际上它是一个非 const
限定版本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
是常量,但它指向的是非常量 int的数组代码>s;而
int const x[5]
表示 x
不是 const 但它指向一个 const int 数组!
进一步阅读此处,感谢@JensGustedt
I learned from C Primer Plus that if you want to protect an array from being accidentally modified by a function, you should add const
modifier before the pointer declaration in the header of function definition.
Following this sensible advice, in the following minimal example, I'm trying to pass a non-constant two-dimensional array array
to the function Sum2D
, one parameter of which is a 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;
}
However, gcc
cannot successfully compile this code without issuing the following warnings:
$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);
^
1) Why the warning?
2) How can I eliminate the "noise"?(Apart from adding const
to array
declaration.)
(If the array
and function both use one-dimensional array, there is no warning.)
System information:
Ubuntu 14.04LTS
Compiler: gcc 4.8.2
This is an unfortunate "bug" in C's design; T (*p)[N]
does not implicitly convert to T const (*p)[N]
. You will have to either use an ugly cast, or have the function parameter not accept const
.
At first sight it looks like this conversion should be legal. C11 6.3.2.3/2:
For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type;
However also look at C11 6.7.3/9 (was /8 in C99):
If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type.
This last quote says that int const[4]
is not considered to be a const
-qualified version of int[4]
. Actually it is a non-const
-qualified array of 4 const int
s. int[4]
and int const[4]
are arrays of different element types.
So 6.3.2.3/2 does not in fact permit int (*)[4]
to be converted to int const (*)[4]
.
Another weird situation where this issue with const
and arrays shows up is when typedefs are in use; for example:
typedef int X[5];
void func1( X const x );
void func1( int const x[5] );
This would cause a compiler error: X const x
means that x
is const, but it is pointing to an array of non-const int
s; whereas int const x[5]
means x
is not const but it is pointing to an array of const ints!
Further reading here, thanks to @JensGustedt
这篇关于将二维数组传递给常量参数的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!