文档章节

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

idreamo
 idreamo
发布于 2016/07/31 07:39
字数 1751
阅读 26
收藏 0

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

© 著作权归作者所有

idreamo
粉丝 18
博文 139
码字总数 224743
作品 0
青岛
产品经理
私信 提问
C Primer Plus 第10章 数组和指针 编程练习答案

1、修改程序清单10.7中的程序rain,使它不使用数组下标,而是使用指针进行计算(程序中仍然需要声明并初始化数组)。 2、编写一个程序,初始化一个double数组,然后把数组内容复制到另外两个...

idreamo
2016/08/14
261
0
C Primer Plus 第10章 数组和指针 10.4 函数、数组和指针

假设您要编写一个对数组进行操作的函数,目的是要此函数返回数组内所有元素的和。假设marbles为这个int数组的名称。应该如何来调用这个函数? 一种合乎情理的猜测如下: totao = sum(marble...

idreamo
2016/07/28
58
0
C Primer Plus 第10章 数组和指针 10.1 数组

10.1 数组 数组由一系列相同的元素构成。 数组声明中包括数组元素的数目和元素的类型。 一些数组声明的例子: float candy[365]; /365个浮点数的数组/ char code[12]; /12个字符的数组/ int...

idreamo
2016/07/21
37
0
C++ primer第二次阅读学习笔记(第4章)

C++语言应尽量使用vector和迭代器类型,应避免使用低级的数组和指针,涉及良好的程序只有在强调速度时才在类实现的内部使用数组和指针。因此要向成为一个真正的C++程序员就要多使用vector和s...

长平狐
2012/10/08
72
0
C Primer Plus 第10章 数组和指针 10.5 指针操作

C提供了6种基本的指针操作,下面的程序将具体演示这些操作。为了显示每一个操作的结果,程序将打印出指针的值(即指针指向的地址)、指针指向地址中存储的内容,以及指针本身的地址(如果您的...

idreamo
2016/07/30
76
0

没有更多内容

加载失败,请刷新页面

加载更多

Kafka 原理和实战

本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/bV8AhqAjQp4a_iXRfobkCQ 作者简介:郑志彬,毕业于华南理工大学计算机科学与技术(双语班)。先后从事过电子商务、开放平...

vivo互联网技术
12分钟前
5
0
java数据类型

基本类型: 整型:Byte,short,int,long 浮点型:float,double 字符型:char 布尔型:boolean 引用类型: 类类型: 接口类型: 数组类型: Byte 1字节 八位 -128 -------- 127 short 2字节...

audience_1
59分钟前
7
0
太全了|万字详解Docker架构原理、功能及使用

一、简介 1、了解Docker的前生LXC LXC为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。相当于C++中的NameSpa...

Java技术剑
今天
13
0
Wifiphisher —— 非常非常非常流氓的 WIFI 网络钓鱼框架

编者注:这是一个非常流氓的 WIFI 网络钓鱼工具,甚至可能是非法的工具(取决于你的使用场景)。在没有事先获得许可的情况下使用 Wifiphisher 攻击基础网络设施将被视为非法活动。使用时请遵...

红薯
今天
57
1
MongoDB 4 on CentOS 7安装指南

本教程为CentOS x86_64 7.x操作系统下,MongoDB Community x86_64 4.2(GA)安装指南。 安装方式一:yum repo在线安装 [此方式较为简单,官方推荐] Step1:新建MongDB社区版Yum镜像源。 # vim ...

王焱君
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部