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

Nai*_*ree 4 c arrays pointers gcc-warning

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

遵循这个明智的建议,在下面的最小例子中,我试图将一个非常数二维数组array传递给函数Sum2D,其中一个参数是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;
}
Run Code Online (Sandbox Code Playgroud)

但是,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);
     ^
Run Code Online (Sandbox Code Playgroud)

1)为什么要警告?

2)我怎样才能消除从将"噪音"?(除了constarray声明.)

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

系统信息:

Ubuntu 14.04LTS

编译器:gcc 4.8.2

M.M*_*M.M 9

这是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的-qualified版本int[4].实际上它是一个const4 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] );
Run Code Online (Sandbox Code Playgroud)

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

在这里进一步阅读,感谢@JensGustedt

  • 在 c23 的最新草案中,文本更改为“如果数组类型的规范包含任何类型限定符,则**数组和元素类型都是如此限定的。”。所以这个问题也许终于解决了 (2认同)