C

C 知识量:16 - 74 - 317

10.6 保护数组中的数据><

数组与函数参数- 10.6.1 -

使用带参数的函数时,传递参数时需要确认是传递某个类型的值,还是传递指向某个类型的指针。一般情况下,只需要传递数值,只有当需要在函数内部影响外部传递的值时,才需要传递指针。

对数组而言,只能传递指针。如果不是这样,就需要分配足够的空间来储存原数组的副本,再把原数组的所有数据拷贝到新数组中,这样的代价太大了,因此,传递指针的效率更高。

问题在于,如果传递的是指针,那么在函数内部对参数(数组元素值)的修改就会直接影响原数组,因此,需要通过某种方式对数据数据进行保护。

对形参使用const- 10.6.2 -

可以在函数原型和函数定义中使用const关键字来起到保护数组数据的作用,例如:

/*函数原型*/
int sum(const int array[], int n); 

/*函数定义*/
int sum(const int array[], int n) {
    int i;
    int total = 0;
    for (i = 0; i < n; i++)
        total += array[i];
    return total;
}

以上代码中的const关键字表明,该函数不能修改array指向的数组中的内容。这样使用const并不是要求原数组是常量,而是该函数在处理数组时会将其视为一个常量,不可更改,这样就可以对数组起到保护作用。

const的其他内容- 10.6.3 -

可以创建const数组、const指针和指向const的指针。

1、指向const的指针。指向const的指针不能用于改变值。例如:

int arr_int[3] = {100, 200, 300};
const int *p = arr_int;

第二行代码将p指向的int类型的值声明为const,这表明不能使用p来更改它所指向的值,比如:

*p = 400;          //不允许
p[2] = 400;        //不允许
arr_int[2] = 400;  //允许,因为arr_int没有被const限定

以上代码中,无论是使用指针表示法还是数组表示法,都不允许使用p来修改它所指向数据的值。但是,可以将p指向别处,例如:p++;是允许的。一般的,指向const的指针通常用于函数的形参中,表明该函数不会使用指针改变数据。

关于指针赋值和const需要注意以下规则:

  • 把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的。例如:

    int r[3] = {1, 2, 3};
    const int l[3] = {4, 5, 6};
    const int *p = r; //有效
    p = l; //有效
    p = &r[2]; //有效
  • 只能把非const数据的地址赋值给普通指针。例如:

    int r[3] = {1, 2, 3};
    const int l[3] = {4, 5, 6};
    int *p = r; //有效
    p = l;      //无效
    p = &r[2];  //有效

鉴于以上规则,对函数的形参使用const不仅能保护数据,还能让函数处理const数组。反正,如果函数没有使用const形参,则不能将const数组名作为实参传递给该函数,因为,C标准规定,使用非const标识符修改const数据导致的结果是未定义的。

2、const指针。const还有一种用法是可以声明并初始化一个不能指向别处的指针,即const指针,注意const的位置:

int r[3] = {1, 2, 3};
int * const p = r; //指向数组的第一个元素
p = &r[2]; //不允许       
*p = 5; //允许

const最后还有一种用法是在创建指针时同时使用两次,该指针既不能更改它所指向的地址,也不能修改指向地址上的值:

int r[3] = {1, 2, 3};
const int * const p = r; //指向数组的第一个元素
p = &r[2]; //不允许       
*p = 5; //不允许