将二维数组传递给常量参数的函数
Pass a two dimensional array to a function of constant parameter
我从C Primer Plus了解到,如果你想保护一个数组不被函数意外修改,你应该在指针声明之前添加const
修饰符在函数定义的头部。
遵循这个明智的建议,在下面的最小示例中,我试图将一个非常量二维数组 array
传递给函数 Sum2D
,其中一个参数是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
无法在不发出以下警告的情况下成功编译此代码:
$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) 为什么会出现警告?
2) 如何消除 "noise"?(除了将 const
添加到 array
声明之外。)
(如果array
和函数都使用一维数组,则没有警告。)
System information:
Ubuntu 14.04LTS
Compiler: gcc 4.8.2
这是 C 语言设计中的不幸 "bug"; T (*p)[N]
不会隐式转换为 T const (*p)[N]
。您将不得不使用丑陋的转换,或者函数参数不接受 const
.
乍一看,这种转换似乎是合法的。 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;
然而也看看 C11 6.7.3/9(在 C99 中是 /8):
If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type.
最后引用的内容是 int const[4]
而不是 被认为是 int[4]
的 const
合格版本。实际上它是一个非 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 数组!
进一步阅读 here,感谢@JensGustedt
您可以在调用函数时对数组进行类型转换。它不会自动将非常量转换为常量。
你可以用这个。
Sum2D( (const int (*)[])array, ROWS );
我从C Primer Plus了解到,如果你想保护一个数组不被函数意外修改,你应该在指针声明之前添加const
修饰符在函数定义的头部。
遵循这个明智的建议,在下面的最小示例中,我试图将一个非常量二维数组 array
传递给函数 Sum2D
,其中一个参数是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
无法在不发出以下警告的情况下成功编译此代码:
$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) 为什么会出现警告?
2) 如何消除 "noise"?(除了将 const
添加到 array
声明之外。)
(如果array
和函数都使用一维数组,则没有警告。)
System information:
Ubuntu 14.04LTS
Compiler: gcc 4.8.2
这是 C 语言设计中的不幸 "bug"; T (*p)[N]
不会隐式转换为 T const (*p)[N]
。您将不得不使用丑陋的转换,或者函数参数不接受 const
.
乍一看,这种转换似乎是合法的。 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;
然而也看看 C11 6.7.3/9(在 C99 中是 /8):
If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type.
最后引用的内容是 int const[4]
而不是 被认为是 int[4]
的 const
合格版本。实际上它是一个非 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 数组!
进一步阅读 here,感谢@JensGustedt
您可以在调用函数时对数组进行类型转换。它不会自动将非常量转换为常量。 你可以用这个。
Sum2D( (const int (*)[])array, ROWS );