7.3 一维数组和指针(课件)-《C语言程序设计》同步教学(天津大学出版社)

2024-12-10
| 21页
| 231人阅读
| 22人下载
普通

内容正文:

《C语言程序设计》 (天津大学出版社) 第7章 指针、函数和数组 7.1 变量的地址和指针 7.2 指针变量 7.3 一维数组和指针 7.4 一维数组和函数 7.5 二维数组和指针 7.6 二维数组和函数 7.7 字符串和指针 7.8 指向函数的指针 7.9 返回指针值的函数 7.10 指针数组和二级指针 7.3 一维数组和指针 7.3.1 数组首地址 7.3.2 数组元素的指针 7.3.3 通过指针引用数组元素 7.3.1 数组首地址 回顾: 数组名就是数组的首地址。因指针变量存储的内容就是一个地址,故理论上就可以直接把数组名赋值给指针变量。 由于C语言的编译系统对于数组中某个元素的表示与指向数组的指针表示某个数组元素的时候是同等对待的,因此对于指向数组的指针是对数组操作的另外一种表现形式。 7.3.1 数组首地址 首先对比变量的地址赋值给指针变量与数组名赋值给指针变量。 int i,*p=&i; //变量使用取地址“&”符号来取得其地址值,赋值给指针 int a[10],*p=a; //数组直接将其名字赋值给指针 可以看到,数组的首地址是可以赋值给指针变量的。数组的声明方式通常为: 类型名 数组名[长度] ; 上述的声明实际上产生了如下的一种内存结构: 上图可以清晰地了解到,数组中任何一个元素的引用方式都是使用:数组名[下标编号]的方式来引用的。数组名作为整个数组的标示,表达为某类型整个数组空间的首地址,以便于使用下标引用方式逐一访问 返回 7.3.2 数组元素的指针 方式一:普通方式 可以使用如下方式来给指针赋值,使得该指针指向数组中的某个元素: 例7.8 给数组元素赋值的普通方式 int a[10],*p; …… p=&a[5]; …… p=&a[0]; …… 分析:语句int a[10],*p;声明了一个数组a,它有十个整型元素。并声明了一个整数指针变量。语句p=&a[5];如果希望访问数组a的第六个元素,则给他制造一个新名字:*p,也就是将数组的第六个元素的地址(&a[5])直接赋值给整型指针变量p。语句p=&a[0];如果希望访问数组a的第一个元素,可以使用上述的办法。这个用法完全等价于p=a ,这是因为第一个元素的地址就是整个数组的首地址 7.3.2 数组元素的指针 方式二:递加方式 假设对指针的定义如下: int a[10],*p=a; 则a数组的任意一个元素可以使用下面的方式来表达: 数组a中的第i个元素的名称是:a[i],也可以是:*(p+i)。 这种方式提供了更加灵活的数组访问方法。 7.3.2 数组元素的指针 上述两种用法可以通过一张图来对比: 返回 7.3.3 通过指针引用数组元素 方法一:普通引用法。当对数组的某个元素直接访问时,可以使用这种方法。 例7.9 数组元素的普通引用 int a[20],*p; p = &a[5]; //取得第六个元素的地址 *p = 34; //给第六个元素赋值为整数34 分析:上述代码的功能为访问数组的第六个元素。语句p = &a[5];的作用是取得第六个元素的地址。语句*p = 34;是给第六个元素赋值为整数34。 很明显,上述的方法只能给数组中的某一个元素赋值,如果希望利用指针给数组中所有元素赋值,则可以如下编写代码: 例7.10 使用指针给数组全部元素赋值为1 int a[20],*p; int i; p = a; for(i=0;i<20;i++,p++) *p= 1; 分析:注意到,上述代码中语句p = a;与语句p=&a[0];等价。该语句的作用为取得数组的首地址。 7.3.3 通过指针引用数组元素 方法二:递加引用。当引用数组元素的时候也可以采用固定首地址,而改变其增量来实现普通方法的赋值方式。 例7.11 数组某一个元素的递加引用 int a[20],*p; int i; p = a; *(p+5) = 34; 分析:上述代码的功能为访问数组的第六个元素。语句p = a;与语句p=&a[0];等价。该语句的作用为取得数组的首地址。语句*(p+5) = 34;作用为给第六个元素赋值为整数34。 例7.12使用指针给数组全部元素赋值为1 int a[20],*p; int i; p = a; //语句p=&a[0];与p=a;等价。该语句的作用为取得数组的首地址。 for(i=0;i<20;i++,p++) *(p+i)= 1; 分析:语句p = a;与语句p=&a[0];等价。该语句的作用为取得数组的首地址。 7.4 一维数组和函数 7.4.1 数组元素做函数参数 7.4.2 数组名做函数参数 7.4.3 数组元素地址做函数参数 7.4.4 函数的指针形参和函数体中数组的区别 7.4.1 数组元素做函数参数 在函数的参数当中,可以使用普通变量(自动变量)。这种用法与使用数组的元素作为参数参数的用法完全一致。即: 例7.13 函数参数使用普通变量与数组元素作为函数参数 int i=5,a[3]={5,5,5}; fun(i); 或者使用fun(a[2]); 分析: 上述两个语句实现了完全相同的功能。就是将值为5的变量传递给函数fun,从传递的参数值、传递方式、传递后的处理机制来看,fun(i)与fun(a[2])没有本质上的区别。这是因为希望传递的参数值为5,变量i与数组的三个元素的值都是5;第二,参数传递时都没有用到&符号来取得地址;第三,都只使用了变量本身。这说明了一个问题:数组中任意一个元素在实质上就是一个普通变量。因此如果不考虑变量名的情况下,上例中的两个语句完全等价。 7.4.1 数组元素做函数参数 还应该特别看到:在调用函数fun时,调用的机制也是完全一样的。即进入fun函数时,产生变量的副本(数组元素作为变量来产生副本),然后进入函数、完成函数功能、退出函数时将产生的副本删除,其存储空间交还给系统。 例7.13中fun(i)与fun(a[2])的调用流程如下图: 返回 7.4.2 数组名做函数参数 数组的中元素作为函数参数的传递过程中传递的是该元素的值。在这个传递过程中,进入函数后为了保证该值不能被改变,故函数为该参数生成了一个副本。在函数退出时,删除该副本的存储空间。这样参数的值既能被函数所使用,又能保证在函数执行过程中参数的值不会变化。理解这个过程类似于理解我们数学上的函数运算: 例7.14 数学的运算关系 y = 2x+6 当 x = 1时,有: y =2*1+6=8 注意到,此时的x仍然等于1. 那么很多时候需要改变数组中的元素值,则此时可以使用两种方式来解决这个问题,第一种方式就是传递数组的首地址,也就是数组名作为函数的参数。 7.4.2 数组名做函数参数 例7.15 有下程序(函数fun只对下标为偶数的元素进行操作)。(2010年9月全国计算机等级考试二级C试题选择题第30题) #include <stdio.h> void fun(int *a,int n) { int i,j,k,t; for (i=0;i<n-1;i+=2) { k=i; for(j=i;j<n;j+=2) if(a[j]>a[k]) k=j; t=a[i]; a[i]=a[k]; a[k]=t; } } main() { int aa[10]={1,2,3,4,5,6,7},i; fun(aa,7); //调用fun函数 for(i=0;i<7;i++) printf("%d,",aa[i]); //打印执行之后的数组值 printf(" "); }   程序运行后的输出结果是:   A)7,2,5,4,3,6,1  B)1,6,3,4,5,2,7   C)7,6,5,4,3,2,1  D)1,7,3,5,6;2,1 答案:选A。 返回 7.4.3 数组元素地址做函数参数 在某些时候仅仅只需要访问数组中的一个元素,则通常无需传递首地址。仅仅只需传递该元素地址即可。 例7.16 访问数组的某一个元素 #include <stdio.h> void fun(int *p) { *p = 6; } main () { int a[10]={1,2,3,4,5,6,7,8,9,10}; int i; printf (" a数组原来的值为: "); for (i=0;i<10;i++)printf (" %d ",a[i]); fun(&a[2]); printf (" a数组现在的值为: "); for (i=0;i<10;i++)printf (" %d ",a[i]); printf (" "); } 运行结果: a数组原来的值为: 1 2 3 4 5 6 7 8 9 10 a数组现在的值为: 2 6 4 5 6 7 8 9 10 分析:上述程序的功能是将数组的第3个元素值打印出来,并将其原来值3改为6。 7.4.3 数组元素地址做函数参数 特别注意到,即便是传递数组中的一个元素地址,也可以访问数组中其他的元素。因为该元素地址已经帮指针定位到了数组的某一个元素的位置。可以通过这个位置推断其他元素的位置。下面我们来看一个例子: 例7.17 通过元素访问数组(2011年9月全国计算机等级考试二级C试题第27题) #include <stdio.h> void fun(int *p) { printf(“%d ”,p[5]); } main() { int a[10]={1,2,3,4,5,6,7,8,9,10}; fun(&a[3]); } 程序运行后的输出结果是 A.5 B.6 C.8 D.9 答案:选D。 返回 7.4.4 函数的指针形参和函数体中数组的区别 为什么有区别? 函数把指向数组的指针作为形参的时候和函数体中的数组是有本质区别的。当指向数组的指针作为函数的参数时,事实上对于实参是一个副本。因此将指向数组的指针参数传递给函数并不改变该参数的具体数值,也就是无法改变该参数。因为即使函数体中对该形参有赋值等操作,也是改变该形参的副本。但是对于函数体中的数组,是进入函数体是分配空间,函数执行结束时被系统收回。因此两者具有显著的区别。 7.4.4 函数的指针形参和函数体中数组的区别 区别一: 将指向数组元素的指针作为函数的形参 如7.17中语句fun(&a[3]);实际上传递给函数的实参是数组a的第四个元素的地址。p使用的仅仅是:数组a的第四个元素的地址。这里的&a[3]使用方法是:取得数组a第四个元素地址,并将其作为常量来赋值给函数fun的变量p来使用。 在例7.15中语句fun(aa,7);使用的是数组的首地址aa(数组名aa),并将数组名值赋值给指针变量a,然后将指针作为数组来使用。事实上这也是可行的。 但是注意到,这种使用方法仅仅是fun函数中的指针变量a与main函数中的数组aa建立了一个临时联系而已。在fun函数中通过这种临时联系来访问main函数中的aa数组。当fun函数执行完毕时,指针变量a的空间会交还给操作系统(注意到此时main函数尚未执行完),这个联系被切断,但是并未将main函数中的aa数组空间交还给操作系统。 将数组地址作为参数时,改变的是该地址对应的数组内容,当函数执行完毕,修改会保存。 7.4.4 函数的指针形参和函数体中数组的区别 区别二: 函数体中的数组 函数体中的数组与参数不同,函数体中数组的作用范围仅仅限于本函数(声明为静态除外)。因此在函数执行完毕之后,该数组空间将不复存在。下一次在调用此函数时,则重新生成一个该函数的调用副本,函数中的数组空间也重新分配。当然,执行结束时,数组空间仍然会还给操作系统。也就是函数中的数组仅在本函数内部有效! 谢谢观看 $$

资源预览图

7.3 一维数组和指针(课件)-《C语言程序设计》同步教学(天津大学出版社)
1
7.3 一维数组和指针(课件)-《C语言程序设计》同步教学(天津大学出版社)
2
7.3 一维数组和指针(课件)-《C语言程序设计》同步教学(天津大学出版社)
3
7.3 一维数组和指针(课件)-《C语言程序设计》同步教学(天津大学出版社)
4
7.3 一维数组和指针(课件)-《C语言程序设计》同步教学(天津大学出版社)
5
7.3 一维数组和指针(课件)-《C语言程序设计》同步教学(天津大学出版社)
6
所属专辑
由于学科网是一个信息分享及获取的平台,不确保部分用户上传资料的 来源及知识产权归属。如您发现相关资料侵犯您的合法权益,请联系学科网,我们核实后将及时进行处理。