这种技术也会带来一些新的问题。一般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; //不容许