C语言程序设计实用教程第8章.ppt_第1页
C语言程序设计实用教程第8章.ppt_第2页
C语言程序设计实用教程第8章.ppt_第3页
C语言程序设计实用教程第8章.ppt_第4页
C语言程序设计实用教程第8章.ppt_第5页
已阅读5页,还剩115页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、2020/10/11,C语言程序设计教程,1,8.1 指针与指针变量 8.2 指向数组的指针变量 8.3 指向字符串的指针变量 8.4 指针数组与命令行参数 8.5 指针与函数 8.6 指针小结,第 8 章 指针,2020/10/11,C语言程序设计教程,2,教学提示 “指针”是C语言中广泛使用的一种数据类型,运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构,实现动态内存分配,不但能很方便地使用数组和字符串,还能像汇编语言一样处理内存地址,从而编出精练而高效的程序。但是,由于指针概念较复杂,使用较灵活,初学者常常感到较难理解,因此,学习时必须从指针的概念入手,正确理解指针

2、及指针在数组和函数方面的应用。 教学目标 要求学生掌握指针的概念和运算规则,掌握用指针访问变量、一维数组和二维数组的方法,以及用指针处理字符串的方法。通过多编程、多上机调试程序来体会指针的概念及其使用的规律,并应用于实际的编程中。,2020/10/11,C语言程序设计教程,3,8.1 指针与指针变量,8.1.1 指针的概念 1.内存与内存地址 内存地址:内存是计算机用于存储数据的存储器,以一个字节作为存储单元,为了便于访问,给每个字节单元一个唯一的编号,第一字节单元编号为0,以后各单元按顺序连续编号,这些单元编号称为内存单元的地址 。 变量地址:变量所分配存储空间的首字节单元地址(字节单元编号

3、)。,2020/10/11,C语言程序设计教程,4,2、变量、变量名、变量的地址、变量值 每个变量都通过变量名与相应的存储单元相连系,具体分配哪些单元给变量,由编译系统完成变量名到对应内存单元地址的变换。 变量分配存储空间的大小由类型决定。 变量的值则是指相应存储单元的内容。,2020/10/11,C语言程序设计教程,5,3、指针、变量的指针和指针变量 指针:就是 “内存单元的地址”。指针指向一个内存单元。 变量的指针:就是“变量的地址”。变量的指针指向一个变量对应的内存单元。 指针变量:就是地址变量。地址(指针)也是数据,可以保存在一个变量中。保存地址(指针)数据的变量称为指针变量。,202

4、0/10/11,C语言程序设计教程,6,系统为特殊变量p(用来存放地址的)分配的存储空间地址是4800,p中保存的是变量a的地址,即4000,当要读取a变量的值12345时,不是直接通过a变量,也不是直接通过保存12345的内存单元的地址4000去取值,而是先通过变量p得到p的值4000,即a的地址,再根据地址4000读取它所指向单元的值12345。,这种间接的通过变量p得到变量a的地址,再存取变量a的值的方式即为“间接存取”。 通常称变量p指向变量a,变量a是变量p所指向的对象,2020/10/11,C语言程序设计教程,7,4、变量值的存取通过变量在内存中的地址进行存取,系统执行“scanf

5、(”%d“,”时,存取变量a值的方式可以有两种: 直接访问直接利用变量的地址进行存取。 1)上例中scanf(“%d”, (定义p1为指向实型变量的指针变量) char *p2; (定义p2为指向字符型变量的指针变量) 在指针变量定义中,*是一个说明符,它表明其后的变量是指针变量,如p是指针变量,而不要认为“*p”是指针变量。 指针变量定义时指定的数据类型不是指针变量本身的数据类型,而是指针变量所指向的对象(或称目标)的数据类型 指针变量存放的是所指向的某个变量的地址值,而普通变量保存的是该变量本身的值 指针变量并不固定指向一个变量,可指向同类型的不同变量,2020/10/11,C语言程序设计

6、教程,12,(1) 指针运算符与地址运算符 与指针引用有关的两个运算符: 语句仅仅定义了指针变量p,但指针变量并未指向确定的变量(或内存单元)。因为这些指针变量还没有赋给确定的地址值,只有将某一具体变量的地址赋给指针变量之后,指针变量才指向确定的变量(内存单元)。 指针变量初始化:在定义指针时同时给指针一个初始值 如: int a,*p=,2020/10/11,C语言程序设计教程,14,8.1.3 指针变量的引用,与指针引用有关的两个运算符: (1) float *pf; 第一行定义了整型变量a,b及指针变量pa,pb。pa、pb还没有被赋值,因此pa、pb没有指向任何变量, 下面语句完成对p

7、a,pb的赋值: pa=,2020/10/11,C语言程序设计教程,17,例如: int j,k; int *pointer1,*pointer2; pointer1=,2020/10/11,C语言程序设计教程,18,(2) 相同类型的指针变量间的赋值,pa与pb都是整型指针变量,它们间可以相互赋值,如:pb=pa; 即 pa,pb都指向变量a,此时a、*pa、*pb是等价的。指针指向变化如下图:,注意:只有相同类型的指针变量才能相互赋值,如pf=pa;是不允许的。因为pa是整型指针,pf是浮点型指针。,2020/10/11,C语言程序设计教程,19,()给指针变量赋空值,给指针变量赋空值,说

8、明该指针不指向任何变量。 “空”指针值用NULL表示,NULL是在头文件stdio.h中预定义的常量,其值为,在使用时应加上预定义行,如: #include stdio.h int *pa=NULL; 亦可以用下面的语句给指针赋“空值”: pa=0; 或: pa=0; 这里指针pa并非指向0地址单元,而是具有一个确定的“空值”,表示pa不指向任何变量。 注意:指针虽然可以赋值0,但却不能把其它的常量地址赋给指针。例如: pa=4000; 是非法的。,2020/10/11,C语言程序设计教程,20,例 8.1 指针定义与初始化,main() int a,b; int *pointer_1,*po

9、inter_2; a=100;b=10; pointer_1= ,2020/10/11,C语言程序设计教程,21,程序运行结果: 100,10 100,10,2020/10/11,C语言程序设计教程,22,例8.2 从键盘上输入两个整数到a、b,按由大到小输出。,#include main( ) int a,b,*pa= /* pa指向大数,pb指向小数*/ ,2020/10/11,C语言程序设计教程,23,若输入: 12 22输出结果: a=12,b=22 max=22,min=12,(b) (c) 指针变化示意图,2020/10/11,C语言程序设计教程,24,2. 指针的算术运算,(1)

10、 加减运算: 一个指针可以加、减一个整数n,其结果与指针所指对象的数据类型有关。指针变量的值应增加或减少“nsizeof(指针类型)”。 加减运算常用于数组的处理。对指向一般数据的指针,加减运算无实际意义。例如: int a10,*p=a,*x; x=p+3; /*实际上是p加上3*2个字节赋给x, x指向数组的第三个分量*/ 对于不同基类型的指针,指针变量“加上”或“减去”一个整数n所移动的字节数是不同的。例如: float a10, *p=a, *x; p=p+3; /*实际上是p加上3*4个字节赋给x, x依然指向数组的第三个分量*/,2020/10/11,C语言程序设计教程,25,(2

11、) 自增自减运算,指针变量自增、自减运算具有上述运算的特点,但有前置后置、先用后用的考虑,务请小心。 例如: int a10, *p=a, *x; x=p+; /* x第一个元素分量, p指向第二个元素*/ x=+p; /* x、 p均指向数组的第二个分量*/ * p+相当于*(p+ +)。 *(p+)与(*p)+ 含义不同,前者表示地址自增,后者表示当前所指向的数据自增。,2020/10/11,C语言程序设计教程,26,2. * 执行了“p= int *p; p= (把数组的首地址赋给指针变量p),p= 把a0元素的地址赋给指针变量p。也就是说,p指向a数组的第一个元素。,2020/10/1

12、1,C语言程序设计教程,30,2020/10/11,C语言程序设计教程,31,C语言规定:数组名代表数组首地址,是一个地址常量。 因此,下面两个语句等价: p= 两句。,2020/10/11,C语言程序设计教程,32,指向数组的指针变量p,a+0,p+1 或 a+1,p+9 或 a+9,*(a+9) 或*(p+9),2020/10/11,C语言程序设计教程,33,8.2.2.通过指针引用数组元素 *p=5; 表示对p当前所指的数组元素赋以一个值5。 C规定:p+1指向数组的下一元素(而不是将p值简单地加1)。p+1意味着使p的原值(地址)加d个字节(d为一个数组元素所占的字节数)。,如果p的初

13、值为 int i; for (i=0;i10;i+) scanf(%d, ,例8.5 用三种方法输出数组全部元素。 (1)下标法,2020/10/11,C语言程序设计教程,36,main() int a10; int i; for (i=0;i10;i+) scanf(%d, ,(2)通过数组名计算数组元素地址,输出元素的值,2020/10/11,C语言程序设计教程,37,(3)用指针变量指向数组元素 main() int a10; int *p,i; for (i=0;i10;i+) scanf(%d, ,三种方法的比较: 用下标法比较直观,能直接知道是第几个元素;而用指针法则执行效率更高。

14、,2020/10/11,C语言程序设计教程,38,使用指针变量时,应注意: (1)指针变量可实现使本身的值改变。 P+合法;但a+不合法(a是数组名,代表数组首地址,在程序运行中是固定不变的。) (2)要注意指针变量的当前值。,2020/10/11,C语言程序设计教程,39,(3)*p+相当于*(p+),因为*与+优先级相同,且结合方向从右向左,其作用是先获得p指向变量的值,然后执行p=p+1; (4)*(p+)与*(+p)意义不同,后者是先p=p+1,再获得p指向的变量值。 若p=a,则输出*(p+)是先输出a0,再让p指向a;输出*(+p)是先使p指向a,再输出p所指的a。 (5)(*p)

15、+表示的是将p指向的变量值+,2020/10/11,C语言程序设计教程,40,8.2.3用数组名作函数参数,用数组名作函数参数时,由于数组名代表的是数组起始地址,因此传递的值是数组首地址,所以要求形参为指针变量。 引入指向数组的指针变量后,数组及指向数组的指针变量作函数参数时,可有种等价形式(本质上是一种,即指针数据作函数参数): (1)形参、实参都用数组名 (2)形参、实参都用指针变量 (3)形参用指针变量、实参用数组名 (4)形参用数组名、实参用指针变量,2020/10/11,C语言程序设计教程,41,例8.4 将数组a中n个整数按相反顺序存放。,算法为:将a0与an-1对换,再a1与an

16、-2 对换,直到将a(n-1/2)与an-int(n-1)/2)对换。今用循环处理此问题,设两个“位置指示变量”i和j,i的初值为0,j的初值为n-1。将ai与aj交换,然后使i的值加1,j的值减1,再将ai与aj交换,直到i=(n-1)/2为止,如图所示。,2020/10/11,C语言程序设计教程,42,2020/10/11,C语言程序设计教程,43,程序如下: void inv(int x ,int n) /*形参x是数组名*/ int temp,i,j, m=(n-1)/2; for(i=0;i=m;i+) j=n-1-i; temp=xi;xi=xj;xj=temp; return;

17、,2020/10/11,C语言程序设计教程,44,main() int i,a10=3,7,9,11,0,6,7,5,4,2; printf(The original array:n); for(i=0;i10;i+) printf(%d,ai); printf(n); inv(a,10); /*实参是数组名*/ printf(The array has been inverted:n); for(i=0;i10;i+) printf(%d,ai); printf(n); ,2020/10/11,C语言程序设计教程,45,对例8.4作一些改动,将函数inv中的形参x改成指针变量。实参为数组名a

18、,即数组a的首地址,将它传给形参指针变量x,这时x就指向a0。x+m是am元素的地址。设i和j以及p都是指针变量,i指向x,j指向x+n-1,使*i与*j交换就是使ai与aj交换。见下例。,2020/10/11,C语言程序设计教程,46,程序如下: void inv(int *x,int n) /*形参x为指针变量*/ int *p,temp,*i,*j,m=(n-1)/2; i=x;j=x+n-1;p=x+m; for(;i=p;i+,j-) temp=*i;*i=*j;*j=temp; ,2020/10/11,C语言程序设计教程,47,main() int i,a10=3,7,9,11,0

19、,6,7,5,4,2; printf(The original array:n); for(i=0;i10;i+) printf(%d,ai); printf(n); inv(a,10); /*实参是数组名*/ printf(The array has benn inverted:n); for(i=0;i10;i+) printf(%d,ai); printf(n);,运行情况与前一程序相同。,2020/10/11,C语言程序设计教程,48,归纳起来,如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关系有以下种: 形参和实参都是数组名。如: main() int a10;

20、 f(a,10) ,f(int x,int n) 这时形参x和实参a共用一段内存单元。,2020/10/11,C语言程序设计教程,49,实参用数组,形参用指针变量。如: main() int a10; f(a,10) ,f(int *x,int n) ,2020/10/11,C语言程序设计教程,50,实参、形参都用指针变量。如: main() int a10,*p=a; f(p,10) ,f(int *x,int n) ,2020/10/11,C语言程序设计教程,51,实参为指针变量,形参为数组名。如: main() int a10,*p=a; f(p,10) ,以上四种方法,本质上都是地址的

21、传递。其中(1)(4)两种只是形式上的不同,实际上都是使用指针变量。,f(int x ,int n) ,2020/10/11,C语言程序设计教程,52,例8.6 用选择法对10个整数排序。,main() int *p,i,a10=3,7,9,11,0,6,7,5,4,2; printf(The original array:n); for(i=0;i10;i+) printf(%d,ai); printf(n); p=a; sort(p,10); for(p=a;pa+10;p+) printf(%d ,*p); printf(n); ,2020/10/11,C语言程序设计教程,53,sort

22、(int x ,int n) int i,j,k,t; for(i=0;ixk) k=j; if(k!=i) t=xi;xi=xk;xk=t; ,说明:函数sort用数组名作为形参,也可改为用指针变量,这时函数的首部可以改为: sort(int *x,int n) 其他可一律不改。这时将x定义为指针变量,在函数中仍可用xi、xk这样的形式表示数组元素,它就是x+i和x+k所指的数组元素。,2020/10/11,C语言程序设计教程,54,8.2.4指向多维数组的指针变量,1.二维数组的地址 设有一个二维数 组a,它有三行四列: int a34=0,1,2,3,4,5,6,7,8,9,10,11

23、数组名a: 代表整个二维数组的首地址,也就是第0行的首地址。 a+i: 代表第i行的首地址。(见下页图),2020/10/11,C语言程序设计教程,55,数组名a代表整个二维数组的首地址:,上图 a数组包含三个元素:a0,a1,a2. 而每个元素又 是一个一维数组,它包含4个元素(即4个列元素), 如:a0又包含:a00,a01,a02,a03.,2020/10/11,C语言程序设计教程,56,2020/10/11,C语言程序设计教程,57,数组及数组元素的地址表示如下: 从二维数组的角度来看,a是二维数组名,a代表整个二维数组的首地址,也是二维数组第0行的首地址,等于1000。a+1代表第一

24、行的首地址,等于1008。如图8.11所示:,2020/10/11,C语言程序设计教程,58,一维数组名ai: 代表第i 行的首地址,即第i行中第0列元素的地址(既 int k,j,*p; for (j=0;j2;j+) /* 方式1 */ for (k=0;k3;k+) printf(%5d,*(aj+k); /* aj是j行首地址,aj+k是j行k列元素的地址*/ putchar(n); ,2020/10/11,C语言程序设计教程,63,接上页:,for (j=0;j2;j+) /* 方式2 */ for (k=0;k3;k+) printf(%5d,*(*(a+j)+k); /* *(a

25、+j)是j行首地址,*(a+j)+k是j行k列元素的地址*/ putchar(n); p=a; /* p指向数组的第一个元素 */ for (j=0;j2;j+) /* 方式3 */ for (k=0;k3;k+) printf(%5d,*(p+); /* 输出p所指示的元素 */ putchar(n); ,2020/10/11,C语言程序设计教程,64,输出的结果是: 0 3 4 5 0 3 4 5 0 3 4 5,2020/10/11,C语言程序设计教程,65,对二维数组,注意区分以下表示的不同含义: a、二维数组名、数组首址是常量指针。 a+i、 如: int a34; int (*p)

26、4; p=a;,2020/10/11,C语言程序设计教程,67,注意: (1)int (*p)4; 定义一个指针变量p ,p 指向包含4个元素的一维数组。 (2)p+i与 *(p+i)的区别: p+i是指向第i行的指针(第i行的首地址); *(p+i)是指向第i行第1个元素的地址; 两者数值相等,但含义不同:p+i 的增值将以行长为单位,而*(p+i)增值将以元素长度为单位。,2020/10/11,C语言程序设计教程,68,即:p+i+1将指向第i行再下一行的首地址,而*(p+i)+1将指向第i行首元素的下一个元素地址。(见下图) 设 int a34,(*p)4; p=a;,如果p先指向a0,

27、则p+1不是指向a01,而是指向a1,2020/10/11,C语言程序设计教程,69,例8.7 main( ) static int a34=1,3,5,7,9,11,13,15,17,19,21,23; int (*p)4,i,j; p=a; scanf(i=%d,j=%d, ,2020/10/11,C语言程序设计教程,70,例8.8用指向二维数组的指针变量输出二维数组,并将数组中的最大元素及所在行列号输出。,main() int a34=1,3,5,7,9,11,13,15,17,19,21,23; int i,j,max,*p; int row=0,col=0; p=a0; /*指针p指

28、向数组a的第0行第0列*/ max=*p; /*先把第一个元素作为最大值*/ for (i=0;i3;i+) printf(“n”); for(j=0;j4;j+) printf(“%5d”,*p); if (max*p) max=*p; row=i;col=j; p+; printf(“n max is:a%2d%2d=%-4d”, row,col,max);,2020/10/11,C语言程序设计教程,71,运行结果: 1357 9111315 17192123 max is:a23=23,2020/10/11,C语言程序设计教程,72,例8.9 用行指针变量输出二维数组,并将数组中的最大元

29、素及所在行列号输出。,main() int a34=1,3,5,7,9,11,13,15,17,19,21,23; int i, j, max, row=0,col=0; int (*p)4; /*定义p为指向一个有4个元素的行指针变量*/ p=a; /*指针p指向数组a的第0行*/ max=*p; /*先把第一个元素作为最大值*/ for (i=0;i3;i+) printf(“n”);,2020/10/11,C语言程序设计教程,73,for(j=0;j4;j+) printf(“%5d”,*(*p+j); /* *(*p+j)相当于*(*(p+0)+j)是第0行第j列的元素 */ if (

30、max*(*p+j) max=*(*p+j); row=i;col=j; p+; /*p指向下一行*/ printf(“n max is:a%2d%2d=%-4d”, row,col,max); ,运行结果与上例相同。,2020/10/11,C语言程序设计教程,74,注意:例8.8与例8.9中p+所在的位置,例8.9中是在外循环内,处理完一行后再下移指针,而例8.8中是在内循环中,每处理完一个元素就下移指针。例8.9中使用的语句p=a,由于p是指向一维数组的行指针变量,与a一样都是二级指针,故可以直接赋值。而此处若改为p=a0或p= printf(%sn,string); 运行时输出:I Lo

31、ve China!,2020/10/11,C语言程序设计教程,76,用字符指针指向字符串: 字符指针变量的定义:char *指针变量 ; 如:char *p; (1) 在定义时初始化指针变量使指针指向一个字符串。 main( ) char *string=“I Love China!” ; (初始化string) printf( %sn, string ); 运行时也输出: I Love China!,2020/10/11,C语言程序设计教程,77,char *str =“I love china”,str140; 等价于下列两句: char *str ; str=“I love china”

32、 ; 以上语句的含义: 定义str为指针变量,它指向字符型数据,且赋值语句把字符串“I love china ”的首地址赋给了指针变量str。 对字符串的整体输出实际上还是从指针所指示的字符开始逐个显示(系统在输出一个字符后自动执行p+),直到遇到字符串结束标志符0为止。而在输入时,亦是将字符串的各字符自动顺序存储在p指示的存储区中,并在最后自动加上 0。,2020/10/11,C语言程序设计教程,78,(2)用指针变量来实现对字符串的访问例8. 8 将一已知字符串第n个字符开始的剩余字符复制到另一字符串中。,main() int i,n; char a=computer; char b10,

33、*p,*q; p=a; q=b; scanf(%d, /*指针指到要复制的第一个字符 */,2020/10/11,C语言程序设计教程,79,for (;*p!=0;p+,q+) *q=*p; *q=0; /* 字符串以0 结尾 */ printf(String a : %sn,a); printf(String b : %sn,b); ,输入: 3 输出: computer mputer 考虑一下,若输出语句改为如下语句会如何? printf(“string a is :%sn”,p); printf(“string b is %sn”,q);,2020/10/11,C语言程序设计教程,80,

34、8.3.2 字符串指针作函数参数,将一个字符串从一个函数传递到另一个函数,可以用地址传递的方法,即用字符数组名作参数或用指向字符串的指针变量作参数。在被调用的函数中可以改变字符串的内容,在主调函数中可以得到改变了的字符串。,2020/10/11,C语言程序设计教程,81,例8.15 用函数调用实现字符串的复制。,void copy_string(char from,char to) int i =0; while(fromi!=0) toi=fromi;i+; toi=0; ,2020/10/11,C语言程序设计教程,82,main() char a=”I am a teacher.”; ch

35、ar b=”you are a student.”; printf(“string a=%snstring b=%sn”,a,b); copy_string(a,b); printf(“nstring a=%snstring b=%sn”,a,b); ,运行结果如下: string a=I am a teacher. string b=you are a student. string a=I am a teacher. string b=I am a teacher.,2020/10/11,C语言程序设计教程,83,8.3.3 字符串数组 字符串数组:是指数组中的每个元素都是一个存放字符串的

36、数组。 字符串数组可以用一个二维字符数组来存储。 例如:char languge3 10; 数组的第一个下标决定字符串的个数,第二个下标是字符串的最大长度(实际最多9个字符,0占一位置)。 可以对字符串数组赋初值。例如: char languge3 10;=“Basic”, “c+”, “pascal”,2020/10/11,C语言程序设计教程,84,其内存存储情况如图8.14所示:,由于字符数组变量在定义时就确定了大小,每行元素都是固定的,而字符串长度不等,这样会浪费存储空间。使用字符型指针数组可以更方便地处理字符串数组。,2020/10/11,C语言程序设计教程,85,8.4 指针数组与命

37、令行参数 8.4.1 指针数组 指针数组:是指针变量的集合。即它的每一个元素都是指针变量,且都具有相同的存储类别和指向相同的数据类型。 指针数组的定义形式为: 类型标识符 *数组名数组长度说明; 例如: int *p10; 由于 比*的优先级高,因此p先与 10结合成p10,而p10正是数组的定义形式,共有10个元素。最后p10与*结合,表示它的各元素可以指向一个整型变量。,2020/10/11,C语言程序设计教程,86,指针数组广泛应用于对字符串的处理 例如有定义: char *p3; 定义了一个具有三个元素p0,p1,p2的指针数组。每个元素都可以指向一个字符数组,或字符串。 若利用数组初

38、始化,则: char *p3= “Basic”, “c+”, “pascal”; p0指向字符串“Basic”; p1指向字符串“c+”; p2指向字符串“pascal” ;,2020/10/11,C语言程序设计教程,87,其存储结构如图8.15所示。 p0指向字符串“BASIC”; p1指向字符串“C+”; p2指向字符串“PASCAL” ;,2020/10/11,C语言程序设计教程,88,例8.9 字符指针数组的赋值 #define NULL 0 main( ) static char a =“Fortran”; static char b =“COBOL”; static char c

39、=“Pascal”; int i; char *p4; p0=a; p1=b; p2=c; p3=NULL; for (i=0;pi!=NULL;i+) printf(“Language %d is %sn”,i+1,pi); ,2020/10/11,C语言程序设计教程,89,例8.10 有若干本书,将书名按字典顺序排序,#include #include main() char *bname4=Programming in ANSI C,BASIC,Visual C+ 6.0 Programming ,TRUBO C 2.0; int i; void sort(char *name,int)

40、; sort(bname,4); /* 排序,改变指针的连接关系*/ printf(n); for (i=0;i4;i+) /* 输出排序结果*/ printf(%8s,bnamei); ,2020/10/11,C语言程序设计教程,90,void sort(char *name, int n) /*选择排序*/char *t; int i,j,k; /* k记录每趟最小值下标 */ for (i=0;i0) k=j; /* 第j个元素更小*/ if (k!=i) /* 最小元素是该趟的第一个元素 则不需交换 */ t=namei;namei=namek;namek=t; ,输出结果为: BAS

41、IC Programming in ANSI C TRUBO C 2.0 Visual C+ 6.0 Programming,2020/10/11,C语言程序设计教程,91,注意: (1)字符数组中每个元素可存放一个字符,而字符指针变量存放字符串首地址,而不是存放在字符指针变量中。 (2)对字符数组,与普通数组一样,不能对其进行整体赋值,只能给各个元素赋值,而字符指针变量可以直接用字符串常量赋值。例如,若有如下定义: char a10; char *p;则语句 a=”computer”;是非法的,因为数组名a是一个常量指针,不能对其赋值。只能对各个元素分别赋值:a0=c;a1=o;a2=m;a

42、3=p; ;a7=r;但语句: p=”computer”; 是合法的。,2020/10/11,C语言程序设计教程,92,8.4.2 指针数组与命令行参数,在操作系统命令状态下,可以输入程序或命令使其运行,称命令行状态。输入的命令(或运行程序)及该命令(或程序)所需的参数称为命令行参数。 如: copy fd fs copy是文件拷贝命令,fd、fs是命令行参数。 main函数是可以有参数的,但与普通函数不同。 带形参的main( )函数的一般形式是: main (int argc, char *argv ) 形参argc记录命令行中字符串的个数,argv是一个字符型指针数组,每一个元素顺序指向

43、命令行中的一个字符串。,2020/10/11,C语言程序设计教程,93,1.main()函数的形参与实参,main()函数由系统自动调用,而不是被程序内部的其它函数调用, main()函数所需的实参不可能由程序内部得到,而是由系统传送。 main()函数所需的实参与形参的传递方式也与一般函数的参数传递不同,实参是在命令行与程序名一同输入,程序名和各实际参数之间都用空格分隔。 格式为:执行程序名 参数1 参数2 参数n 形参argc为命令行中参数的个数(包括执行程序名),其值大于或等于1,而不是象普通C语言函数一样接受第一个实参。 形参argv是一个指针数组,其元素依次指向命令行中以空格分开的各

44、字符串。 即:第一个指针argv0指向的是程序名字符串,argv1指向参数1,argv2指向参数2,argvn 指向参数n。,2020/10/11,C语言程序设计教程,94,2.命令行参数的传递示例例8.11 分析下列程序,指出其执行结果,该程序命名为exam.c,经编译连接后生成的可执行程序为exam.exe,#include main (int argc , char * argv ) int i=0; printf(“argc=%dn”,argc); while (argc =1) printf(“n参数%d:%s”,i,*argv); i+; argc-;argv+; ,2020/10

45、/11,C语言程序设计教程,95,输出结果: argc=4 参数0:exam 参数1:Turbo_c 参数2:C+ 参数3:Vc 程序开始运行后,系统将命令行中字符串个数送argc,将四个字符串实参:exam、Turbo_c、C+、Vc的首地址分别传给字符指针数组元素argv0、argv1、argv2、argv3。,若运行该程序时的命令行输入的是: exam Turbo_c C+ Vc,2020/10/11,C语言程序设计教程,96,8.5指针与函数,8.5.1指针变量作为函数参数 利用指针作函数参数,可以实现函数之间多个数据的传递,当形参为指针变量时,其对应实参可以是指针变量或存储单元地址。

46、 函数形参为指针变量,用指针变量或变量地址作实参。 函数形参为指针变量,用指针变量作为函数的实参。,2020/10/11,C语言程序设计教程,97,例8.12 编写一个交换两个变量的函数,在主程序中调用,实现两个变量值的交换。,#include main() int a,b; int *pa,*pb; void swap(int *p1,int *p2); /*函数声明*/ scanf(%d%d, ,2020/10/11,C语言程序设计教程,98,void swap(int *p1,int *p2) int temp; temp=*p1; *p1=*p2; *p2=temp; ,注意:被调用函

47、数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值。,程序运行结果如下: 输入: 12 22 输出: a=22,b=12,2020/10/11,C语言程序设计教程,99,(2)函数形参为指针变量,用变量地址作为函数的实参。,例8.13 将例8.12中的函数调用改为用变量地址作为实参。 void swap(int *p1,int *p2) int temp; temp=*p1; *p1= *p2; *p2=temp; ,2020/10/11,C语言程序设计教程,100,main() int a,b; scanf(%d%d, ,程序运行结果如下: 输入: 12 22 输出: a=2

48、2,b=12,2020/10/11,C语言程序设计教程,101,该函数的功能是将形参p1和p2的指针值互相交换。虽然指针p1和p2的指针值被交换了,但由于指针变量的值也遵循单向传递的原则,不会因为指针形参值的改变而影响到指针实参的值。主函数中变量a和b的值并没有交换。因此,仅交换函数中指针形参的值,并不能交换a和b的值,这一点是初学者容易犯的错误。,考虑:若函数写为如下的形式 void swap(int *p1 ,int *p2) int *p; p=p1; p1=p2; p2=p; ,2020/10/11,C语言程序设计教程,102,另一个容易犯的错误是将函数写成如下形式: void swa

49、p(int *p1 ,int *p2) int *p; *p=*p1; *p1=*p2; *p2=*p; ,其中,将p也定义为指针变量,但由于在函数中并未对p赋初值,p的值是不确定的,即指向一个未知的存储单元。此时对p的引用可能会导致不可预料的后果,因此,要特别小心。,总结:为了利用被调用函数改变的变量值,应该使用指针(或指针变量)作函数实参。其机制为:在执行被调用函数时,使形参指针变量所指向的变量的值发生变化;函数调用结束后,通过不变的实参指针(或实参指针变量)将变化的值保留下来。,2020/10/11,C语言程序设计教程,103,8.5.2指针函数,指针函数是指函数的返回值是指针的函数。

50、指针函数的定义形式: 类型标识符 *函数名(形参表) 例如: int *fun(int a,int b) 函数体语句 ,2020/10/11,C语言程序设计教程,104,fun()函数即是一个指针函数,要求返回值是一个int型指针,这时要求在函数体中有返回指针或地址的语句,形如: return (,2020/10/11,C语言程序设计教程,105,例8.14 分析如下程序 main( ) int a,b,*p; int *max(int x, int y); int *maxp(int *,int *); scanf(“%d, %d”, ,2020/10/11,C语言程序设计教程,106,in

51、t *max(int x, int y) if xy return ( /*指针变量q作为指针函数的返回值,输入:8,9 输出:max=9 maxp=9,返回指针的函数是很有用的,在库函数中有许多是返回指针值的,如字符串函数strcat()、strcpy(),动态存储分配函数malloc()、calloc()等,读者应熟练掌握。,2020/10/11,C语言程序设计教程,107,8.5.3指向函数的指针,一个函数包括一组指令序列,存储在某一段内存中,这段内存空间的起始地址称为函数的入口地址,称函数入口地址为函数的指针。函数名代表函数的入口地址。 可以定义一个指针变量,其值等于该函数的入口地址,

52、指向这个函数,这样通过这个指针变量也能调用这个函数。这种指针变量称为指向函数的指针变量。 定义指向函数的指针变量的一般形式为: 类型标识符(*指针变量名)();,2020/10/11,C语言程序设计教程,108,例如: int (*p)(); /* 指针变量p可以指向一个整型函数*/ float (*q)(); /* 指针变量q可以指向一个浮点型函数*/ 上面定义的指向函数的指针变量,亦象其它指针变量一样要赋以地址值才能引用。当将某个函数的入口地址赋给指向函数的指针变量,就可用该指针变量来调用所指向的函数。函数名代表函数的入口地址,给函数指针赋初值:只需将函数名(函数的入口地址值)赋给指针变量

53、即可。 例如 int (*p)( ); int max(int a,int b); 则有赋值语句:p=max; /* p指向函数max(),即将函数的入口地址值赋给指针变量p*/,2020/10/11,C语言程序设计教程,109,这时我们就可以用指针来调用函数了,这种调用方式称为间接调用。 如:a=(*p)(m,n) 这与前面所讲的函数调用:a=max(m,n) 是等价的。后者称为直接调用。 指针调用函数的一般形式为: (*指针变量)(实参表); 如上例:m=(*p)(12,22); /*比较 m=max(12,22); */,2020/10/11,C语言程序设计教程,110,例8.15 函数

54、max()用来求一维数组中元素的最大值,在主调函数中用函数名调用该函数与用函数指针调用该函数来实现。 #include stdio.h #define M 8 main() float sumf,sump; float aM=11,2,-3,4.5,5,69,7,80; float (*p)(); /*定义指向函数的指针p*/ float max(float a,int n); /*函数声明*/ p=max; /*函数名(函数入口地址)赋给指针p*/ sump=(*p)(a,M); /*用指针方式调用函数*/,2020/10/11,C语言程序设计教程,111,sumf=max(a,M); /*用函数名调用max()函数*/ printf(sump=%.2fn,sump); printf(sumf=%.2fn,sumf),float max(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论