将二维数组传递给常量参数的函数 [英] Pass a two dimensional array to a function of constant parameter

查看:52
本文介绍了将二维数组传递给常量参数的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从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 是常量,但它指向的是非常量 ints;而 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 ints. 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 ints; 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆