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

标签 c arrays pointers gcc-warning

我从 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) 我怎样才能消除“噪音”?(除了将 const 添加到 array 声明之外。)

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

System information:

Ubuntu 14.04LTS

Compiler: gcc 4.8.2

最佳答案

这是 C 设计中的一个不幸的“错误”; 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] 被认为是 constint[ 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,但它指向一个非常量 ints;而 int const x[5] 意味着 x 不是 const 但它指向一个 const 整数数组!

进一步阅读 here ,感谢@JensGustedt

关于c - 将二维数组传递给常量参数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29323297/

相关文章:

c - 如果允许任何 c 标准,则在其下允许本地功能

c - 为什么此 C 代码将局部结构视为指针,而它似乎不是指针?

c - 从不兼容的指针警告初始化

c - fprintf 不会将以零结尾的十六进制数正确写入文件

javascript - 使用数组索引搜索字符串字母

javascript - AngularJS 基于复选框选择显示数组

c++ - 数组中存储的地址值如何与其自己的地址相同,它应该指向某个不同的地址(&arr [0])?

c - 取消引用的指针更改函数调用中的地址

c - 如何获取从索引a到索引b的数组的最大元素?

javascript - 在 AngularJS 应用程序中本地保存数组数据,以便在两个应用程序之间共享