tceic.com
简单学习网 让学习变简单
当前位置:首页 >> 学科竞赛 >>

第九讲 指针和数组


示例程序
指针能够很有效地处理数组。我们将看到,数组名同时也是该数组首元素的地 址。也就是说,如果a是一个数组,下面的式子是正确的。 a==&a[0] 两者都是常量,因为在程序的运行过程中它们保持不变,然而可以把它们赋给 指针变量,然后你可以修改指针变量的值,如下面的这个程序。
#include<stdio.h> #define SIZE

4 int main(void) { 程序输出如下: short dates[SIZE]; short *pti; short double short index; pointer + 0: 0022FEDC 0022FEB8 double bills[SIZE]; pointer + 1: 0022FEDE 0022FEC0 double *ptf; pti=dates; pointer + 2: 0022FEE0 0022FEC8 ptf=bills; pointer + 3: 0022FEE2 0022FED0 printf("%21s %8s\n","short","double"); for(index=0;index<SIZE;index++) printf("pointer + %d: %p %p\n",index,pti+index,ptf+index); return 0; }

程序分析
? 在C中,对一个指针加1的结果是对该指针增加1个存储单元(storage unit)。对 于数组而言,地址会增加到下一个元素的地址,而不是下一个字节。这就是为什 么在声明指针时必须声明它所指向对象的类型。计算机需要知道存储对象所用的 字节数,所以只有地址信息是不够的(即使指针是指向标量的,也需要声明指针 类型;否则*pt操作不能正确返回数值)。
? 指针的数值就是他所指向的对象的地址。很多种计算机都是以字节编址的,这意 味着对每个内存字节顺序进行编号。对于包含多个字节的数据类型,比如double 类型的变量,对象的地址通常指的是其首字节的地址。

? 在指针前运用运算符*就可以得到该指针所指向的对象的数值。
? 对指针加1,等价于对指针的值加上它指向的对象的字节大小。

程序分析
下面的等式体现出了C的优点: dates+2==&dates[2] *(dates+2)==dates[2]
/*相同的地址*/ /*相同的值*/

这些关系总结了数组和指针间的密切关系:可以用指针标识数组的每个元素, 并得到每个元素的数值。从本质上说,对同一个对象有两种不同的符号表示方法。 C 语言标准在描述数组时,确实借助了指针的概念。例如,定义 ar[n] 时,意思是 *(ar+n),即“寻址到内存中的ar,然后移动n个单位,再取出数值”。 顺便提一下,请注意区分*(dates+2)和*dates+2。间接运算符(*)的优先级高 于+,因此后者等价于:(*dates)+2。

示例程序
理解了数组和指针的关系,编程的时候就可以方便地选择两者中任意一种方法。 例如:下面这个程序编译后的运行输出结果一样。
#include<stdio.h> #define MONTHS 12 int main(void) { int days[MONTHS]={31,28,31,30,31,30,31,31,30,31,30,31}; int index; for(index=0;index<MONTHS;index++) printf("Month %2d has %d days.\n",index+1,*(days+index)); //与days[index]相同 return 0; 程序输出如下: }
Month 1 has 31 days. Month 2 has 28 days. Month 3 has 31 days. Month 4 has 30 days. Month 5 has 31 days. Month 6 has 30 days. Month 7 has 31 days. Month 8 has 31 days. Month 9 has 30 days. Month 10 has 31 days. Month 11 has 30 days. Month 12 has 31 days.

程序分析
此 处 , days 是 数 组 元 素 的 地 址 : days+index 是 元 素 days[index] 的 地 址 ; *(days+index)是这个元素的值,与days[index]等价。每次循环会依次引用一个数组 元素,并打印出该数组元素的内容。 这样编写程序有优势吗?不一定。该示例程序只是用来表明指针和数组是两个 等效的方法。这个程序表明可以用指针来标记数组;反之亦然,也可以用数组方式 来访问指针。当设计程序时,如果用到数组作为函数的参数,那么这一点就很重要 了。

函数、数组和指针
假设我们要编写一个对数组进行操作的函数,目的是要此函数返回数组内所有 元素的和,并假设a为这个int数组的名称。应该如何调用这个函数?一种合乎情理 的猜测如下: total=sum(a); //可能的调用 那么这里的sum函数的原型应该是什么样的呢?数组名同时代表数组首元素的 地址,因此实际参数a是一个int的地址,应该把它赋给一个类型为指向 int的指针的 形式参量: int sum(int *ar); //相应的原型 函数sum()从该参数可以得到什么信息呢?它得到数组元素首元素的地址,而 且知道可以从此地址找到一个int。请注意它无从知道数组中元素的数量。于是在函 数的定义中有两种选择,第一种是在函数代码中写上固定的数组大小,如下所示:
int sum(int *ar) { int i; int total=0; for(i=0;i<10;i++) total+=ar[i]; return total; } 上面的代码利用了这样的事实:正如可以在指针符号中使用数组名一样,也可以在数 组符号中使用指针。

函数、数组和指针
这种函数定义是有限制的,它仅在数组大小为10时工作。更灵活的方法是把数 组大小作为第二个参数传递给函数。 int sum(int *ar,int n) //更通用的方法 { int i; int total=0; for(i=0;i<n;i++) total+=ar[i]; return total; } 这里的第一个参数把数组地址和数组类型的信息传递给函数,第二个参数把数 组中的元素个数传递给函数。 此外,关于函数参量还有一件需要说明的事情:在函数原型或函数定义头的场 合中(并且只有在这两种场合中),可以用int ar[]代替int *ar: Int sum(int ar[],int n); 无论在任何情况下,形式int *ar都表示ar是指向int的指针。形式int ar[]也可以表 示ar是指向int的指针,但只是在声明形式参量时才可以这样使用。使用第二种形式 可以提醒读者ar不仅指向一个int数值,而且它指向的这个int是一个数组中的元素。

一、使用指针参数
使用数组的函数需要知道何时开始和何时结束数组。函数sum()使用一个指针 参量来确定数组的开始点,使用一个整数参量来指明数组的元素个数(指针参量同 时确定了数组中数据的类型)。但是这并不是向函数传递数组信息的唯一方法。另 一种方法是传递两个指针,第一个指针指明数组的起始地址(同前面的方法相同), 第二个指针指明数组的结束地址。下面的程序示意了这种方法。
#include<stdio.h> #define SIZE 10 int sum(int *start,int *end); int main(void) { int a[SIZE]={20,10,5,39,4,16,19,26,31,20}; long answer; answer=sum(a,a+SIZE); printf("The total number of a is %ld.\n",answer); return 0; } int sum(int *start,int *end) { int total=0; while(start<end) { total+=*start; start++; } return total;

程序分析
由于指针start最初指向a的首元素,因此执行赋值表达式total+=*start时,把首 元素的值(即20)加到total上。然后表达式start++ 使指针变量 start增加1,从而指 向数组的下一个元素。Start是指向int的指针,因此当start增加1时它将增加1个int的 大小。 请注意前后两个函数结束加法循环的方式不一样。前一个sum()函数使用数组 元素的个数做为第二个参数,循环利用这个值来控制循环次数: for(i=0;i<10;i++) total+=ar[i]; 而后一个sum()函数则使用第二个指针来控制循环次数: while(start<end) { total+=*start; start++; } 因为这是一个对于不相等关系的判断,所以处理的最后一个元素将是 end所指 向的位置之前的元素。这就意味着end实际指向的位置是在数组最后一个元素之后。 C保证在为数组分配存储空间的时候,指向数组之后的第一个位置的指针也是合法 的。这使上面例子中采用的结构是有效的,因为start在循环中最后得到的值是 end。 请注意使用这种“越界”指针可使函数调用的形式更整洁: answer=sum(a,a+SIZE);

程序分析
由于索引是从0开始的,因此a+SIZE指向数组结尾处之后的下一个元素。如果 让end指向最后一个元素而不是指向数组结尾处之后的下一个元素,就需要使用下 面的代码: answer=sum(a,a+SIZE-1); 这种写法不仅仅看起来不整洁,而且也不容易被记住,因此比较容易导致编程 错误。顺便说一句,尽管C保证指针a+SIZE是合法的,但是对a[SIZE](即该地址存 储的内容)不作任何保证。
从前面的介绍可以看出,处理数组的函数实际上是使用指针作为参数的。但是 在编写处理数组的函数时,数组符号和指针符号都是可以选用的。如果使用数组符 号,则函数处理数组这一事实更加明显。 在C中,两个表达式ar[i]和*(ar+i)的意义是等价的。而且不管ar是一个数组名还 是一个指针变量,这两个表达式都可以工作。然而,只有当ar是一个指针变量时, 才可以使用ar++这样的表达式。

二、指针操作
C提供了9种基本的指针操作。
?赋值(assignment)——可以把一个地址赋给指针变量。通常使用①数组名或②地址运算符&来进 行地址赋值。注意:地址应该和指针类型兼容。也就是说不能把一个char类型的地址赋给一个指向 int的指针。 ?求值( value-finding )或取值(dereferencing )——运算符*可以取出指针指向的地址中存储的数 值。 ?取指针地址——指针变量同其它变量一样具有地址和数值,使用运算符&可以得到存储指针本身的 地址。 ?将一个整数加给一个指针——可以使用+运算符来把一个整数加给一个指针,或者把一个指针加给 一个正数。这两种情况下,这个正数都会和指针所指类型的字节数相乘,然后所得的结果会加到初 识地址上。 ?增加指针的值——可以通多一般的加法或增量运算符来增加一个指针的值。队指向某数组元素的 指针做增量运算,可以让指针指向该数组的下一个元素。 ?从指针中减去一个整数——可以使用-运算符来从一个指针中减去一个整数。指针必须是第一个操 作数。这个整数会和指针所指类型的字节数相乘,然后所得的结果会从初识地址中减掉。 ?减小指针的值——指针当然也可以做减量运算。

二、指针操作
C提供了9种基本的指针操作。
?求差值(differencing )——可以求出两个指针间的差值。通常对分别指向同一个数组内两个元素 的指针求差值,可以求出元素之间的距离。差值的单位是相应类型的大小。

?比较——可以使用关系运算符来比较两个指针的值,前提是两个指针具有相同的类型。
注意:这里有两种形式的减法。可以用一个指针减掉另一个指针得到一个整数,也可以从一个 指针中减去一个整数得到一个指针。 在进行指针的增量和减量运算时,需要牢记一些注意事项。计算机并不检查指针是否仍指向某 个数组元素。C保证指向数组元素的指针和指向数组后的第一个地址的指针都是。但是如果指针在 进行了增量或减量运算后超出了这个范围,后果将是未知的。另外,可以对指向一个数组元素的指 针进行取值运算。但是不能对指向数组后的第一个地址的指针进行取值运算,尽管这样的指针是合 法的。 切记:当创建一个指针时,系统只分配了用来存储指针本身的内存空间,并不分配用来存储数 据的内存空间。因此在使用指针之前,必须给它赋予一个已分配的内存地址。比如,可以把一个已 存在的变量地址赋给指针变量(当您使用带有一个指针参量的函数时,就属于这种情况)。总之, 使用指针时一定要注意,不能对未初始化的指针赋值!

Int *pi; *pi=100

//未初始化的指针 //不能这样做,危险!


推荐相关:

实验七 指针与数组 参考答案

实验九-指针与数组_答案 暂无评价 15页 免费 实验十四 指针与数组 5页 免费 ...[i]-第 i 行的首地址 p=s; for(i=0;i<3;i++) for( j=0 //分别...


指针数组和数组指针的区别

这次要给学生讲指针这一章,特意关注了一下。 而网上一些相关回答也没严格区分...但可以这样 *p=a; 这里*p 表示指针数组第一个元素的值,a 的首地址的值。 ...


计算机二级c语言第九章 数组和指针习题与答案

第九章 数组和指针 1、有以下程序 main() { int a[]={2,4,6,8,10}, y=0, x, *p; p=&a[1]; for(x= 1; x< 3; x++) y += p[x]; ...


数组指针与指针数组的区别

但可以这样 *p=a; 这里*p 表示指针数组第一个元素的值,a 的首地址的值。 例如:int *p[4],由于[]比*优先级更高,因此 p 先与[4]结合,形成 p[4]的...


实验六 指针与数组

实验六 指针与数组_化学_自然科学_专业资料。实验六 指针与数组一、实验目的 (1)熟悉指针的概念,并掌握指针变量的定义及使用。 (2)掌握数组的指针和指向数组的...


指针与数组笔试题

指针与数组笔试题_计算机软件及应用_IT/计算机_专业资料 暂无评价|0人阅读|0次下载|举报文档 指针与数组笔试题_计算机软件及应用_IT/计算机_专业资料。1. 请问...


数组指针和指针数组的区别=

数组指针和指针数组的区别 数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明 p 是一个指针,指向一个整型的一维数组,这个一维数组的长度是 n,...


数组和指针的异同

数组和指针的异同_IT/计算机_专业资料。节选自《C专家...第二条语句声明 y 是一个 int 型数组, 长度尚未...http请求处理流程(讲的很... 6页 免费©...


指针数组和指向数组的指针

10.3 数组指针和指向数组的指针变量 一个变量有一个地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元, 它们都有相应的地址。所谓数组的指针是指...

网站首页 | 网站地图
All rights reserved Powered by 简单学习网 www.tceic.com
copyright ©right 2010-2021。
文档资料库内容来自网络,如有侵犯请联系客服。zhit325@126.com