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

原创
2016/07/31 07:39
阅读数 166

这种技术也会带来一些新的问题。通常C传递数据的值,其原因是要保护原始数据的完整性。函数使用原始数据的一份拷贝,这样就不会意外的修改原始数据。但是,由于处理数组的函数直接操作原始数据,所以它能够修改原数据。有时候这正是我们需要的,比如给某个数组的所有元素加上同一个值;然而也许其他函数并不希望修改数据,比如只是计算数组中所有元素的和。

10.6.1  对形式参量使用 const

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

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

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

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

{ ... }

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

需要理解的是,这样使用const并不要求原始数据是固定不变的。这只是说明函数在处理数组时,应把数组当作是固定不变的。使用const可以对数组提供保护,就像按值传递可以对基本类型提供保护一样,可以阻止函数修改调用函数中的数据 。

总之,如果函数想修改数组,那么在声明数组参量时就不要使用const;如果函数不需要修改数组,那么在声明数组参量时最好使用const。

请看程序清单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;  //不允许

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部