C Primer Plus 第10章 数组和指针 10.6 保护数组的内容

这种技术也会带来一些新的问题。一般C传递数据的值,其缘由是要保护原始数据的完整性。函数使用原始数据的一份拷贝,这样就不会意外的修改原始数据。可是,因为处理数组的函数直接操做原始数据,因此它可以修改原数据。有时候这正是咱们须要的,好比给某个数组的全部元素加上同一个值;然而也许其余函数并不但愿修改数据,好比只是计算数组中全部元素的和。数组

10.6.1  对形式参量使用 const函数

在k&RC中,避免此类错误唯一的方法就是警戒不出错。ANSI C中有另外一种方法。spa

若是设计意图是函数不改变数组的内容,那么能够在函数原型和定义的形式参量声明中使用关键字const。例如sum()的原型的定义应该以下:设计

int sum (const int ar[],int n);  //原型指针

int sum (const int ar[],int n)   //定义code

{ ... }ip

这告知编译器:函数应当把ar所指向的数组做为包含常量数据的数组对待。这样若是你意外的使用诸如ar[i]++之类的表达式,编译器将会发现这个错误并生成一条错误消息,通知您函数试图修改常量。原型

须要理解的是,这样使用const并不要求原始数据是固定不变的。这只是说明函数在处理数组时,应把数组看成是固定不变的。使用const能够对数组提供保护,就像按值传递能够对基本类型提供保护同样,能够阻止函数修改调用函数中的数据 。编译器

总之,若是函数想修改数组,那么在声明数组参量时就不要使用const;若是函数不须要修改数组,那么在声明数组参量时最好使用const。io

请看程序清单10.14中的程序,其中一个函数显示数组,另外一个函数对数组的每个元素乘上一个给定的数值。由于第一个函数不须要修改数组,因此使用const;由于第二个函数须要修改数组,因此不使用const。

程序清单10.14  atf.c程序

/*arf.c --处理数组的函数*/
#include <stdio.h>
#define SIZE 5
void show_array (const double ar[],int n);
void mult_array (double ar[],int n,double mult);
int main(void)
{
    double dip[SIZE]={20.0,17.66,8.2,15.3,22.22};

    printf("The original dip array: \n");
    show_array(dip,SIZE);
    mult_array(dip,SIZE,2.5);
    printf("The dip array after calling mult_array(): \n");
    show_array(dip,SIZE);
    return 0;
}
/*显示数组内容*/
void show_array (const double ar[],int n)
{
    int i;
    for(i=0;i<n;i++)
        printf("%8.3f ",ar[i]);
    putchar('\n');
}
/*用同一个乘数去乘每一个数组元素*/
void mult_array (double ar[],int n,double mult)
{
    int i;
    for(i=0;i<n;i++)
        ar[i]*=mult;
}

输出结果以下:

The original dip array:
  20.000   17.660    8.200   15.300   22.220
The dip array after calling mult_array():
  50.000   44.150   20.500   38.250   55.550

请注意两个函数都是void类型的。函数mult_array()确实使数组dip获得了新的值,但不是使用rerutn机制实现的。

10.6.2  有关const的其余内容

前面咱们讲过可使用const来建立符号常量

const double PI=3.14156;

以上也可使用#define指令实现。但使用const还能够建立数组常量、指针常量以及指向常量的指针

指向常量的指针不能用于修改数值,考虑如下代码:

double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};

const double *pd=retes;  //pd指向数组开始处

第二行代码把pd声明为指向const double 的指针。这样,就不能使用pd来修改它所指向的数值。

*pd = 29.89;  //不容许

pd[2] = 222.22;  //不容许

rates[0] = 99.99  //容许,由于rates不是常量

不管使用数组符号仍是指针符号,都不能使用pd修改所指向的数据的值。另外须要注意,还可让pd指向其余地址:

pd++;  /*让pd指向rates[1] -这是容许的*/

一般把指向常量的指针用做函数参量,以代表函数不会用这个指针来修改数据。例如,程序清单10.14中函数show_array()的原型能够以下定义:

void show_array(const double *ar,int n);

关于指针赋值和const有一些规则须要注意。

首先,将常量或很是量数据的地址赋给指向常量的指针是合法的

double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};

const double locked[4]={0.08, 0.075, 0.0725, 0.07};

const double * pc = rates;  //合法

pc = locked;  //合法

pc = &rates[3];  //合法

然而,只有很是量数据的地址才能够赋给普通指针

double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};

const double locked[4]={0.08, 0.075, 0.0725, 0.07};

double * pc = rates;  //合法

pc = locked;  //非法

pc = &rates[3];  //合法

这样的规则是合理的。不然,您就可使用指针来修改被认为是常量的数据。

这些规则的实践结果是:像show_array()这样的函数能够接受普通数组和常量数组的名称做为实际参数由于两种参数均可以赋给指向常量的指针:

show_array(rares,5);  //合法

show_array(locked,4);  //合法

可是,像mult_array()这样的函数不能接受常量数组的名称做为参数:

mult_array(rates,5,1.2);  //合法

mult_array(locked,4,1.2);  //非法

所以,在函数参量定义中使用const,不只能够修护数据,并且使函数可使用声明为const的数组。

const还有不少的用法。例如,您可使用关键字const来声明并初始化指针,以保证指针不会指向别处,关键在于const的位置:

double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};

double * const pc = rates;  //pc指向数组的开始处

pc = &rates[2];  //不容许

*pc = 92.99;  //能够,更改rates[0]的值

这样的指针仍然能够用来修改数据,可是它只能指向最初赋给它的地址。

最后,可使用两个const来建立指针,这样的指针即不能够更改所指向的地址,也不能够修改所指向的数据:

double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};

const double * const pc = rates; 

pc = &rates[2];  //不容许

*pc = 92.99;  //不容许

相关文章
相关标签/搜索