版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、程序设计基础(C语言)东北大学高级语言程序设计课程组课程网站: 程序设计基础(C语言)指针3n指针是语言的重要概念之一n它使语言比之其它程序设计语言更具特色n深入理解语言特性n指针是学习使用语言的难点n指针是C语言的一个重要概念n正确而灵活地使用指针n有效地描述各种复杂的数据结构n动态地分配内存空间n自由地在函数之间传递各种类型的数据n使程序简洁、紧凑,执行效率高n指针是C提供的一种数据结构n属于简单数据类型n它的意义和作用明显又不同于一般的数据类型概述4A直接直接BA间接间接1.预备知识n直接和间接的含义n内存n即内部存储器,是由内存单元组成n特点n存储单元是线性连续的n存储单元的最小单位为
2、字节51.预备知识n内存n计算机的内存中的每一个字节都有一个编号n所有的内存单元都要统一进行“编号”n这个编号就是该字节在整个内存中的“地址”n所有的内存单元都要有地址n每一内存单元具有唯一的内存地址n系统为每一个已定义的变量分配一定存储空间n使变量名与内存的一个地址相对应n通过地址我们就能够访问该地址所标识的存储单元n程序处理过程n需要根据地址取出变量所对应的内存单元中存放的值n参与计算/操作n处理结果存入相应的变量名所对应的内存单元 0 1 2 3 2000 0 1 2 3 2000地址地址4545变量内容变量内容61.预备知识n计算机的寻址方式n直接寻址n间接寻址存入存入/ /取出取出
3、数据数据 数据数据内存内存地址地址 1003 1004 1008 100C 1003 1004 1008 100C 存入存入/ /取出取出B B单元单元内存内存地址地址 1050 1051 3020 3021 1050 1051 3020 3021 地地 址址数据数据 数据数据A A单元单元71.预备知识nC语言如何处理?n高级语言中的变量具有三个属性n变量的名、变量的值、变量的地址n编程者使用c程序的一个变量n定义变量的数据类型n数据类型决定了一个变量在内存中所占用的存储空间的大小n变量在内存中总是占用几个连续的字节n定义变量名n语言的编译系统会根据变量的数据类型为该变量分配内存单元n确定变
4、量的地址n变量的地址就是为变量分配的内存单元的起始编号n就可以通过变量名对内存中变量对应的地址进行操作81.预备知识2000200020022002200120012003200320042004200520052006200620072007地址地址变量名变量名 变量类型变量类型 字节数字节数 i int 2 i int 21010a3.14159263.1415926pi float 4 pi float 4 ch char 1 ch char 191.预备知识nC语言如何处理?n直接访问n通过变量名访问数据的方式称为直接访问 n例如:printf(%d, n); /* 通过变量名访问变量
5、n */ n间接访问n如果将变量n的地址存放在另一个变量pn中,通过访问变量pn,间接达到访问变量i的目的,这种方式称为变量的间接访问 n在C语言中,间接寻址方式访问内存是通过指针变量实现的n指针变量通过直接寻址方式访问获得的是一个地址值n在该地址起始的一个存储单元中存放程序需要的数据1010101020022002200420041010101030030010121012102.指针变量n定义n用于指向其他变量的变量 n指针变量是一个变量n和普通变量一样占用一定的存储空间n该存储空间存放的是一个地址值而不是普通的数据值n指针变量是一个地址变量n指针变量的值是一个内存单元的地址n它指向另一个
6、变量的值n指针就是地址n当将变量的地址存入指针变量后,就说这个指针指向了该变量n指针变量只能存放某一数据类型的变量n问题?n变量的类型和指向变量的类型之间的区别?112.指针变量n指针变量的声明n指针变量与一般的变量的区别n格式 *指针变量名;n说明n数据类型表示指针所指向的数据的数据类型n提示:不是指针变量的数据类型n*是指针的标志,表示它后面的变量名是指针类型n例nint *i_p;/*定义了指针变量i_p ,指向的对象类型为整型*/n char *cp;/*定义了指针变量cp, 指向的对象类型为字符型*/122.指针变量n指针变量的声明n提示n声明语句的*只能用于指针变量n这种表示方式说
7、明被声明的变量是一个指针n*不针对声明语句中的所有变量n每一个指针都必须在其名字前面有一个前缀*声明n例如:int *pt1,pt2;npt2为整型变量而不是整型指针变量n指针变量名是pt1而不是*pt1n指针变量只能指向定义时规定的类型变量n只有同一数据类型的地 址才能存放在指向该类型变量的指针变量中n例如: int *ip;/*ip指针变量只能存放整型变量的地址*/132.指针变量n指针变量的声明n提示n在定义指针时可以用void将指针定义为空类型n不指定指针指向一个确定的类型n区分“值”与“内容”的含义n例如n整型变量是内容为整型数值的变量n整型指针变量是存放整型变量地址的变量n在引用指
8、针变量前必须首先让指针指向一个变量n这一点非常重要n定义指针变量后,并未确定该变量指向何处,该变量的值是不确定的指针指针P P指针变量指针变量p p的地址的地址内存单元内存单元142.指针变量n指针变量初始化n在使用指针变量时,要首先对指针变量进行初始化,让指针变量指向一个具体的变量n初始化的方式n使用赋值语句n例nint i, *pi; /* 说明指针变量pa和变量a */pi=&i; /*使用取地址符&把变量i的地址赋值给指针变量:pi指向了整型变量i */ n说明指针变量的时候同时进行n例:使用先声明变量的地址nint i,*pi=&i;n问题?n写成int *p
9、a; *pa=&a;会出现什么问题? 152.指针变量n指针变量初始化n在使用指针变量时,要首先对指针变量进行初始化,让指针变量指向一个具体的变量n初始化的方式n给指针变量赋空值(赋值为符号常量NULL )n例np=NULL;/*表示指针p为空,没有指向任何对象*/ n一般情况下给没有初始值的指针变量赋值为NULLn实际上,NULL是整数0,系统保证0单元不存储任何数据的值(地址)n NULL是头文件以及其它几个头文件中定义的符号常量指针指针P P空地址空地址NULLNULL指针变量指针变量内存单元内存单元162.指针变量n指针变量初始化n提示n在使用指针之前一定要对其进行初始化n否则
10、程序不知道指向何处n系统在执行程序时会给出如下的信息nrun-time error R6001null pointer assigmentn或者引起更严重的错误系统崩溃n对未使用的指针应该赋以空值NULLn表明它未指向任何地方n这并不是对指针的初始化n只是 表示该指针未被使用而已172.指针变量n指针变量初始化n提示n一个指针变量赋空值与不赋值是完全不同的概念n前者是有不指向任何变量的地址n后者是一个不确定的随机值n这时指针可能指向一个事先未指定的数据n利用空指针可以简化程序代码、提高效率n指针变量应具有无符号整型类型的值n存放的是地址n由于地址本身的特征,不能将一个整型值赋给一个指针变量。同
11、样也不能将指针变量的值赋给一个整型变量n 例如:int *p;p=2000;(非法)182.指针变量n指针变量初始化n提示n用void将指针定义为空类型n即不指定指针指向一个确定的类型n例如:void *p;/*表示指针变量P不指向一个确定的类型*/ n它的作用仅用来存放一个地址n作用n任何类型的指针都可以赋给指向void类型的指针n指向void类型的指针也可以赋给任何类型的指针n但是:不能复引用void*类型的指针n编译器不能根据类型确定它引用的字节数n常见错误n将一种类型的指针赋给另一种类型的指针,而这两种指针都不是void*类型【例】定义指针变量【例】定义指针变量 void void *
12、 *p2p2; int int * *p1p1,i=5i=5; p1=&i p1=&i;p2=p1p2=p1; 演示演示9191。C C 193.指针变量n指针变量的运算n语言提供的指针运算n取地址运算(&)n作用是取变量的地址n运算对象必须是(任意类型的)变量n例如n&i /*表示求变量 i的地址*/nint x=3, *p;p=&x /* &表示取的地址,将变量地址赋给指针变量p */n提示n&是一个单目运算符,它返回变量的地址n&的操作数必须是一个变量n取地址运算符“&”是取操作对象的地址而不是其值203.指针变量n
13、指针变量的运算n语言提供的指针运算n取内容运算(*)n运算对象必须是指针(该指针所指向的对象可以是任意类型)n作用是取指针所指向变量的内容。*也称为“间接引用运算符”或“指针的复引用”n 例如na=*prt; /*表示指针 prt所指向变量的内容赋a*/ nint a=3, *p, x;pa=&a;nx=*pa; /* *pa表示取指针变量pa所指单元的内容,即变量a的值,则x=3 */ 213.指针变量n指针变量的引用n当指针变量定义和赋值之后,引用变量的方式n用变量名直接引用n例如nscanf(“%d”,&a);/*在函数中直接使用变量a的地址 */n通过指向变量的指针间接
14、引用n利用指针变量,提供对变量的一种“间接访问”形式n指针变量的引用形式 *指针变量 n含义是指针变量所指向的值n例如nint a=3,*pa;pa=&a; /* 指针pa指向变量a*/printf(%dn,*pa); /* 通过 * 运算符实现间接访问 */223.指针变量n指针变量的引用n例:用指针变量进行输入输出 main main()() int int * *p p,m m; scanf scanf(“%d”“%d”,&m&m);); p=&m p=&m; printf printf(“%d”“%d”,* *p p);); main main(
15、)() int int * *p p,m m; p=&m p=&m; scanf scanf(“%d”“%d”, p p );); printf printf(“%d”“%d”, m m );); 运行结果完全一样。请思考一下若将程序修改为如下形式:运行结果完全一样。请思考一下若将程序修改为如下形式:mainmain()() int int * *p p,m m; scanf scanf(“%d”“%d”, p p );); p=&m p=&m; printf printf(“%d”“%d”, m m );); 会产生什么结果?会产生什么结果?23#includ
16、e#includemain()main() int a, int a, * *aptr;aptr; a=7; a=7; aptr=&a; aptr=&a; printf(“The address of a is %pn” printf(“The address of a is %pn” ”The value of aptr is %pnn”,&a,aptr); ”The value of aptr is %pnn”,&a,aptr); printf(“The value of a is %dn” printf(“The value of a is %dn” ”T
17、he value of ”The value of * *aptr is %dnn”,a,aptr is %dnn”,a,* *aptr);aptr); printf(“Proving that printf(“Proving that * * and & are complements of” and & are complements of” ”each other .n& ”each other .n&* *aptr=%pnaptr=%pn* *&aptr=%pn”, &aptr=%pn”, &* *aptr,aptr,* *&am
18、p;aptr);&aptr); 3.指针变量n指针变量的引用n例:本程序演示了指针运算符的用法24【例】【例】 main main()() int int * *p1p1,* *p2p2; int i=10 int i=10,j=20j=20; p1=&i p1=&i; p2=&j p2=&j; p2=p1 p2=p1; printf printf(“* *p1=%dp1=%d;* *p2=%dn” p2=%dn” ,* *p1p1,* *p2p2);); printf printf(“i=%d“i=%d;j=%dn” j=%dn” ,i i,j j);
19、); printf printf(“p1=%p“p1=%p,p2=%pn”p2=%pn”,p1p1,p2p2);); 本题中若本题中若* *p2=p2=* *p1p1?将将p1p1指向变量的值传递给指向变量的值传递给* * p2 p2的内的内存单元。即存单元。即j j的内存单元中,的内存单元中,P2P2和和p1p1中存放的地址并不发生变化。中存放的地址并不发生变化。结果为:结果为: * *p1=10p1=10;* *p2=10p2=10 i=10 i=10;j=20j=20结果:结果: * *p1=10p1=10;* *p2=10p2=10 i=10 i=10;j=10j=103.指针变量25
20、3.指针变量n指针变量的提示n取内容运算符*p与定义指针变量时使用的*p含义不同n定义时的*p表示的是一个指针变量,该变量指向一个整型变量的地址n取内容运算符*p则表示取指针变量的内容,即另一个变量值n对指针的引用需要*和&n&用于求任一类型变量的指针,求出的指针具有对应的类型n*和指针一起使用时被认为是同类型的一个变量n可以参与该类型变量的一切运算n*和&是一对功能恰好相反的运算操作符n在实际应用中, 应特别注意&和*的操作对象n&的操作对象是一个“变量”n*的操作对象是一个“地址”264.指针与数组n指针和数组紧密联系n对数组元素的访问可以通过指针和
21、借助数组元素下标的方法实现n凡是由数组下标完成的操作皆可用指针来实现n“下标方式“访问数组元素n通过数组的下标唯一确定了某个数组元素在数组中的顺序和存储地址n例如:int a5 = 1, 2, 3, 4, 5, x x=a0; /* 通过下标将第1个元素的值赋给x=1 */ 274.指针与数组n指针和数组紧密联系n对数组元素的访问可以通过指针和借助数组元素下标的方法实现n凡是由数组下标完成的操作皆可用指针来实现n指针最常见的一种用途就是指向数组元素n当一个指针指向数组后,就可以灵活快速地处理数组元素,从而体现出指针的优点n“指针方式”访问数组中的元素n一个数组(/数组元素)有相应的地址,可以将
22、数组的起始地址或某一个数组元素的地址放到一个指针变量中n数组的指针就是数组的起始地址(数组名),既数组第一个元素的地址(&数组名0)n数组元素的指针就是该数组元素的地址284.指针与数组n指针和数组紧密联系n分析程序n语言中规定n数组第1个(下标为0)元素的地址就是数组的首地址n数组名代表的就是数组的首地址n数组名代表的一个地址常量,是数组的首地址n它不同于指针变量#include main ( ) int a = 1, 2, 3, 4, 5 ; int x, y, *pt,*p2; pt = &a0; x = *(pt+2); p2=&a4; y=pt4; print
23、f (*p=%d, x=%d, y=%dn, *pt, x,y,*p2); 294.指针与数组n指针和数组紧密联系n语言中规定说明n当指针指向数组首地址时(pt=ary或pt=&ary0时) 指针可以向数组一样使用n提示n对数组元素的访问,下标方式和指针方式是等价的n从语言系统内部处理机制上讲,指针方式效率高n指针方式不如下标方式直观n下标方式可以直截了当地看出要访问的是数组中的哪个元素n指向数组的指针变量,进行运算以后,指针变量的值改变了,其当前指向的是哪一个数组元素不再是一目了然* *(pt+2pt+2)pt2pt2 ary2 ary2 * *(ary+2ary+2)304.指针与
24、数组n指针和数组的可替代性nC语言中的指针和数组几乎可以互换n指针可以用来完成涉及数组下标的操作n例如:int a10;int *p;n若p=&a0;或 p=a;则p就指向了数组a的首址n当p指向了一维数组a,指针对数组元素可以表示:np+n与a+n( n (偏移量)的取值为09 )表示数组元素 an的地址,既&an n*(p+n)和*(a+n) 表示数组元素an ( n的取值为09 ) n指向数组的指针变量也可以用数组的下标形式pn,其效果相当于*(p+n),等价于an314.指针与数组n指针和数组的可替代性n例#include void strcopy1(char str,
25、const char *); void strcopy2(char str,const char *); main( ) char str110,*str2=“teacher”; char str310,*str4=“boys and girls”; strcopy1 (str1,str2); printf(“str1=%sn”,str1); strcopy2(str3,str4); printf(“str3=%sn”,str3); 这两个函数都将一这两个函数都将一个字符串(可能是个字符串(可能是一个字符数组)拷一个字符数组)拷贝到一个字符数组贝到一个字符数组中,比较这两个函中,比较这两个函数
26、原型可以发现其数原型可以发现其形式是相同的,虽形式是相同的,虽然这两个函数完成然这两个函数完成同样的功能,但是同样的功能,但是他们的实现过程是他们的实现过程是不同的。不同的。32/* 采用数组表示法将采用数组表示法将s2拷贝到拷贝到s1.*/void strcopy1(char *s1,const char *s2) int i; for(i=0;s1i=s2i;i+) ; /*函数体中没有任何动作函数体中没有任何动作*/ /* 采用指针表示法将采用指针表示法将s2拷贝到拷贝到s1.*/ void strcopy2(char *s1,const char *s2) for( ;*s1=*s2;
27、s1+,s2+) ; /*函数体中没有任何动作函数体中没有任何动作*/ 4.指针与数组334.指针与数组n指针和数组的可替代性n数组的表示法n数组/下标n指针/偏移量n利用*p、*(p+1)、来代表数组a0、a1n数组/偏移量n对数组的引用以*a、*(a+ 1)、代替a0、a9n n指针/下标n表达式p1引用了数组元素a134【例【例1 1 】采用指针】采用指针/ /偏移量表示的地址法输入输出数组元素。偏移量表示的地址法输入输出数组元素。mainmain()() int n,a10, int n,a10,* *pa=a; /pa=a; /* *定义时对指针变量初始化定义时对指针变量初始化* *
28、/ / for (n=0;n=9;n+) for (n=0;n=9;n+) scanf scanf(“%d”,pa+n“%d”,pa+n); ; for for(n=0;n=9;n+n=0;n=9;n+) printf printf(“%d”,“%d”,* *(pa+npa+n); ; printf printf(“n”“n”); ; 【例【例2 2】采用表示的数组】采用表示的数组/ /偏移量表示的地址法输入输出数组元素。偏移量表示的地址法输入输出数组元素。 main main()() int n,a10, int n,a10,* *pa=a; /pa=a; /* *定义时对指针变量初始化定义
29、时对指针变量初始化* */ / for (n=0;n=9;n+) for (n=0;n=9;n+) scanf scanf(“%d”,a+n“%d”,a+n); ; for for(n=0;n=9;n+n=0;n=9;n+) printf printf(“%d”,“%d”,* *(a+na+n); ; printf printf(“n”“n”); ; 4.指针与数组35【例【例3 3】采用指针】采用指针/ /下标法输入输出数组元素。下标法输入输出数组元素。 main main()() int n,a10, int n,a10,* *pa=a;pa=a; for (n=0;n=9;n+) for
30、 (n=0;n=9;n+) scanf scanf(“%d”,&pan“%d”,&pan); ; for for(n=0;n=9;n+n=0;n=9;n+) printf printf(“%d”,pan“%d”,pan); ; printf printf(“n”“n”); ; 【例【例4 4】采用数组】采用数组/ /下标法输入输出数组元素。下标法输入输出数组元素。 main main()() int n,a10; int n,a10; for (n=0;n=9;n+) for (n=0;n=9;n+) scanf scanf(“%d”,&an“%d”,&an);
31、 ; for for(n=0;n=9;n+n=0;n=9;n+) printf printf(“%d”,an“%d”,an); ; printf printf(“n”“n”); ; 4.指针与数组36mainmain()()int ary4=int ary4=2,4,8,162,4,8,16; int int * *iprtiprt,i i; iprt=ary iprt=ary; / /* *按正序输出数组元素按正序输出数组元素* */ / for for (i=0i=0;i4i=0i=0;i- -i- -) printf printf(“%d” “%d” ,* *( iprt+i iprt+
32、i );); prntf prntf(“n”“n”);); 4.指针与数组n指针和数组的可替代性n例:将一个数组按正向、逆向输出374.指针与数组n指针和数组的关系n提示n指针变量与数组的区别n指针变量是地址变量,数组名是地址常量n指针变量的内容可以在程序运行过程中被修改,数组名一旦被声明,它的值在整个程序运行中是不能改变n(p+1)和 *(a+ 1)都可以表示数组元素a1, 两者并不能完全等价n对 数组a只能引用,不能修改n实际上就是指针与指针变量的区别n对于数组名,虽然可以使用它得到其元素的值,但它仅表示数组的首地址,不能将其改变n试图用指针算术运算修改数组名是一种语法错误384.指针与数
33、组n指针和数组的关系n提示n指针变量与数组的区别n指针变量可以改变其自身的值,应该特别注意其的当前值n 例如:对上例程序中的a和pa,若有程序段:n pa=a;printf(”%dn”,*pa);n pa+;printf(“%dn”,*pa);n第一个printf输出的是a0的值n第二个printf则输出的是a1的值n指向数组的指针在数组处理时不要越界n由于C语言不检查数组越界,对一个仅有10个元素的数组a引用第11个元素a10时系统仍按 *(a+10)处理,发生错误394.指针与数组n指针的运算n指针的运算旨在针对数组进行n指针的运算n指针与正整数的加减运算n两个指针的减法运算n两个指针的关
34、系运算n禁止的运算n指针做乘除法运算n指针进行位操作运算n指针与浮点型数据运算n两个指针相加没有意义n指针运算的结果依赖于指针所指向对象的大小n指向对象的数据类型404.指针与数组n指针的运算n指针与正整数的加减运算n该指针下移或上移整型值所指定个数的存储单元的内存地址n存储单元的大小就是该指针的数据类型所需要的内存的大小np+(-)i*sizeof(type)n对指针的加/减(整数)操作运算在用指针访问数组元素是经常用到n表达式:p+n表示指针p所指向当前元素之后的第n个元素n而表达式:p-n表示指针p所指向当前元素之前的第n个元素指针变量指针变量ptr内存内存地址地址20002001200
35、2200320042005200620072008414.指针与数组n指针的运算n指针与正整数的加减运算n例如: int a10 ,*p; n p=a;(或p=&a0 ;)p+ip+i a10 a10 a0 a0 a1 a1 ai ai a9 a9p pp-ip-i a10 a10 a0 a0 a1 a1 ai ai a9 a9200020022004200+2*i2018p p4.指针与数组n指针的运算n指针与正整数的加减运算n自增/自减n指针的自增(+)/自减(-)运算分别表示将指针移动到下一个/上一个存储单元并指向新的数据np+的含义n指针加,指向数组中的下一个元素np-的含义n
36、指针减,指向数组中的前一个元素main()int *prt; int arrary=2,4,6,8,10; prt=array; prt+=3; prt-; prt-=2; prt+; 96。C array5 array5 array0 array0 array1 array1 array2 array2 array3 array3 array4 array42 24 46 68 810102000200020022002200420042006200620082008arrayarrayprtprt(1)(1)(3)(3)(5 5)(2)(2)434.指针与数组n指针的运算n提示n例如:in
37、t a5,*pa:pa=a;npa+; /*使pa指向下一个元素a1;*/n*pa; /*指针所指向的数组名(或变量或数组元素)*/n*pa+; /*先取出pa所指向元素的值 (*pa),后pa+1送 n 与pa。由于+与*的优先级相同,自右向左的结 n 合方向,所以它等价于*(pa+);*/n*(+pa);/*先令pa加1,再取pa指向的值*/n(*pa)+; /*pa所指向的元素的值加1,即(a0)+*/n对于-运算同上444.指针与数组n指针的运算n两个指针的减法运算n减法运算的含义n当两个指针指向同一数组中的元素时np-q表示计算两个指针相差的存储单元个数n计算公式为n n提示n只有当
38、两个指针指向同一数组中的元素时才可进行两个指针的减法运算prt1-prt2= (prt1的值的值-prt2的值)的值)/指针的数据类型的所占字节数指针的数据类型的所占字节数454.指针与数组n指针的运算n两个指针的减法运算n例:计算一个字符串的长度(不用strlen函数)#include main()() int len; char a80 ; gets(a);); puts(a);); len=lenth(a);); printf(“%dn” ,len);); lenth(char *p) char *q=p; while (*q!=0) q+; return(q-p);); 464.指针与
39、数组n指针的运算n两个指针的关系运算n比较两个指针的含义n比较两个存储单元的地址(相对位置)n除非两个指针指向同一数组,否则这种比较是没有意义的n比较两个指向同一数组的指针反映的是指针所指向元素的先后顺序n任何指针p与NULL进行“p=NULL”或“p!=NULL”运算均有意义n“p=NULL”是当指针p为空时成立n“p!=NULL”的含义是当p不为空时成立n例如:有两个指针ptr1和ptr2nif (ptr1ptr2)n printf(“ptr1 points to lower memory than ptr2n”);47例1: 以下程序的输出结果是: #include main( ) in
40、t x =10,20,30,40,50,60; int *p=x; *(p+4)+=6; printf(“%d,%d”,8,*(p+4); A) 10,46 B) 0,56 C) 10,56 D) 50,46 例例2: 已知:已知: int a10=1,2,3,4,5,6,7,8,9,10; int *p=a; 则不能表示数组则不能表示数组a中元素的表达中元素的表达 式是:式是: A)*p B)a10 C)*a D)ap-a4.指针与数组484.指针与数组n指针的运算n提示n数组名代表数组的首地址n固定的,不允许修改的n不能对数组名采用 +/-操作n指针的算术运算除了应用于数组外没有什么意义n
41、除数组外,不能认为两个数据类型相同的变量在内存中是连续存储的n指针的运算与其基类型有关n通常情况下允许一个指针或多个指针指向同一个目标n常见错误n对不指向数组的指针进行算术运算n指针的运算结果超出的数组的范围495.指针与字符串n可以通过字符数组和字符型指针处理字符串n例如:n字符数组实现的方式n char ch =“this is a book!” ; n printf (“%sn” ,ch);n对字符数组初始化nch是字符数组n它存放了一个字符串n字符指针实现的方式n char *ch=“this is a book!” ;n printf (“%sn” ,ch);n是对字符指针初始化n*
42、ch是字符指针n它指向的是一个字符串常量的首地址,即指向字符串的首地址505.指针与字符串n可以通过字符数组和字符型指针处理字符串n字符指针与字符数组区别nchar *ch字符指针是一个变量n指向字符串的第一个字符n可以改变字符指针使它指向不同的字符串nchar ch 是一个字符数组n一个足以存放字符串和空字符0的一维数组n可以改变数组中保存的内容n数组名 ch是一个不可改变的常量nC语言规定n一个指针类型的变量如果指向对象为字符型n可以对其赋值(或初始化)字符串常量n此时字符指针指向的就是用来保存字符串的字符数组的首地址515.指针与字符串n可以通过字符数组和字符型指针处理字符串nC语言规定
43、n一个指针类型的变量如果指向对象为字符型n可以对其赋值(或初始化)字符串常量n此时字符指针指向的就是用来保存字符串的字符数组的首地址n定义n应用n可以使用字符指针指向一个字符类型的数据n可以使用字符指针访问字符串常量(另一种方法为字符数组)n将“good”赋予指针p并不是将字符串的字符赋予p,n是将“good”在内存中的存储区的起始地址赋给pmainmain( ) char char * *pcpc;char chchar ch; pc=&ch pc=&ch; scanf scanf(“%c” “%c” ,pcpc);); printf printf(“%c” “%c” ,ch
44、ch);); char char * *p p;p=“good” p=“good” ;525.指针与字符串n字符指针n应用n例如np+1作首地址;输出结果为bcn提示n赋值时,字符串的结束标志0是系统自动增加的n在输出或处理字符串指针变量和由字符数组组成的字符串时只要指出指针变量或字符数组的名字n对于其它类型的数组,不能只使用数组名,输出或处理全部元素n使用指针编写的字符串处理程序比使用数组方式处理字符串的程序更简洁、更方便n在C语言中,大量使用指针对字符串进行各种处理n在处理字符串的函数中,一般都使用字符指针作为形参 p pp+1p+1 p+2 p+2 a a b b c c00char c
45、har * *p=“abc” p=“abc” ; printf printf(“%s” “%s” ,p+1p+1););535.指针与字符串n指针与字符串的应用n例:字符串连接的一个程序n说明n在处理字符串时(包括它作为函数参数使用时),只需要指定其变量名,无须指出字符串的长度n对字符串str,若写成*str则变成了该字符串的第一个字符,表达式*(str+i)则是表示该字符串的第i+1个字符#include main() char *str1=“People” ; char *str2=“teacher”; char *str3=“n”; strcat(str1,str2); strcat (
46、str1,str3); printf(“%sn”,str1); main()() char *str=“A string!n”; printf(“%s”,str); /*整个字符串操作整个字符串操作*/ for(;*str!=0;) printf(“%c”,*(str+); /*单个字符操作单个字符操作*/ 545.指针与字符串n指针与字符串的应用n例:设计程序,将两个字符串连接起来n不要用strcat函数#include main()() char s180,s280 ; printf(“n input string1:”);); gets(s1);); printf(“n input st
47、ring2:”);); gets(s2);); stringcat(s1,s2);); printf(“n new string:%s”,s1);); stringcat(char *s1,char *s2) while (*s1!=0)s1+; while (*s2!=0) *s1=*s2; s1+; s2+; *s1=0; 555.指针与字符串n指针与字符串的应用n例:编写程序判定一个字符在一个字符串中出现的次数,如果该字符不出现则返回0值n算法n从头开始扫描字符串的每一个字符n若当前字符等于字符串中的字符时,次数计数器加1n直到字符串中的所有字符比较完成56#include main()
48、() char *str,c; printf(“enter a string:n”);); gets(str);); printf(“enter a char:n”);); c=getchar();(); printf(“counts:%dn” ,char_count(str,c);); int char_count(char *string,char letter) int count=0; while (*string) if (*string+= =letter) count+; return(count);); 5.指针与字符串576.指针与函数n函数与指针之间有着密切的关系n包含三种
49、含义n指针作为函数的参数n函数的返回值为指针n指向函数的指针 586.指针与函数n指针作为函数的参数n调用函数并希望改变参数的值时,指针做函数参数非常实用n按址传递n当函数要求能够修改调用函数中的一个或多个值,或能够传递指向大型数据对象的地址以避免开销很大的传值调用n通过变量的地址就可以通过地址间接访问变量的数值n指针是变量的地址n指针作函数的参数就是在函数间传递变量的地址n函数间传递的不再是变量中的数据,而是变量的地址n变量的地址在调用函数时作为实参,被调用函数使用指针变量作为形参接收传递的地址地址地址实参指针实参指针地址地址形参指针形参指针传递传递变量的值变量的值变量变量i i地址地址59
50、6.指针与函数n指针作为函数的参数n要求n在调用函数时以地址做参数传递n当将变量的地址传递给被调函数后,在调用函数的函数体中采用间接引用运算符*修改内存单元中的该变量的值n实参的数据类型要与作为形参的指针所指的对象的数据类型一致n如果是变量的值需要修改,则在变量前面使用&来实现变量的地址n如果是数组的内容需要修改,则直接使用数组名n常见的错误n在需要复引用(*)一个指针来获取指针所指向的值时没有复引用该指针606.指针与函数n指针作为函数的参数n典型例题:比较变量与指针变量的传递方式n变量传递#include void swap(int p1,int p2);); main()() i
51、nt x1=100,x2=200; printf(“before swap:x1=%d,x2=%d” ,x1,x2);); swap(x1,x2);); printf(“after swap:x1=%d,x2=%d” ,x1,x2);); void swap (int p1,int p2) int temp; temp=p1; p1=p2; p2=temp; 运行结果:运行结果:x1=100,x2=200 x1=100,x2=200 x1=100,x2=200 x1=100,x2=200形参形参p1p1与与p2p2的单元值发生交换与实参的单元值发生交换与实参x1x1和和x2x2无关。无关。61
52、6.指针与函数n指针作为函数的参数n典型例题:比较变量与指针变量的传递方式n指针传递#include int swap(int* p1,int* p2);); main()() int x1=100,x2=200; printf(“before swap:x1=%d,x2=%d” ,x1,x2);); swap(&x1,&x2);); printf(“after swap:x1=%d,x2=%d” ,x1,x2);); void swap (int *p1,int *p2)int temp; temp=*p1; *p1=*p2; *p2=temp; 指针作为参数时并未改变实参的
53、值指针作为参数时并未改变实参的值而是改变了所指向单元中的内容而是改变了所指向单元中的内容626.指针与函数n指针作为函数的参数n在主调函数中,传递的是两个变量的地址n并没有试图改变调用函数时的参数,而只是利用了指针变量的特性,改变了指针变量所指向单元的内容nswap根据得到的两个变量的地址将指针指向的变量中的数据进行调换,swap就是在要调换数据的两个实际变量的存储单元上进行的数据交换n交换的结果自然带回到主调函数main中n问题?n如果将例题中的swap()函数写出如下的形式,那么主调函数中的实参x1和x2的值能否改变呢?swap(p1,p2) int *p1,*p2; int *temp;
54、 temp=p1; p1=p2; p2=temp; 636.指针与函数n指针作为函数的参数n提示n地址作为函数的参数必须定义一个接收地址的指针参数(形参为指针类型)n例如: void max(int *mptr,int *nptr)n在使用函数之前先检查一下函数原型,确定该函数是否能够修改传递给它的值n函数原型中没有必要指出指针名,但是要指出指针类型n例如:函数原型void max(int *,int *);n用指针作为函数参数并在调用时传递地址作为实参这样可以改变主调函数中变量的值n不能通过改变指针形参的值而使指针实参改变n因为C语言中参数传递具有“单向性”646.指针与函数n指针作为函数的
55、参数n提示n除非主调函数明确地要求修被调函数环境中的参数变量,否则用传值调用给函数传递参数n传值调用只能在被调函数中修改一个值n要在被调函数中修改多个值必须使用传址调用n如果传递给函数的值没有(或不应该)在函数体内被修改,应该用 const限定符声明该值以防止被意外地修改n如果试图在被调函数中修改用 const限定符声明的值,编译器回给出警告信息或给出错误报文n常见错误n没有意识到传址调用需要指针做参数,而是把值传递给参数656.指针与函数n指针作为函数的参数n例:输入三个数,按大小顺序排序main() int a,b,c; scanf(“%d%d%d”,&a,&b,&
56、c); exchange(&a,&b,&c); printf(“n%d,%d,%dn”,a,b,c); exchange(p1,p2,p3) int *p1,*p2,*p3; if (*p1*p2) swap(p1,p2); if(*p1*p3) swap(p1,p3); if(*p2*p3) swap(p2,p3); void swap (int *p1,int *p2) int temp; temp=*p1; *p1=*p2; *p2=temp; 666.指针与函数n指针作为函数的参数n例:用传址方法将字符串中的小写字母转换为大写字母。#includevoid convtoupper(char *); main( ) char string=“characters CHARacters”
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 小学二年级第一学期班主任工作计划12篇
- 竞选班干部演讲稿范文汇编9篇
- 社会实践活动总结【6篇】
- 行政部个人年终工作总结怎么写
- 车间火灾安全
- 单位统计个人工作总结范例
- 校园安全主题演讲稿集锦15篇
- 出国金融案例分享会
- 奋进新时代争做追梦人征文10篇
- 二年级班先进班集体事迹材料【五篇】
- 社区获得性肺炎指南
- GB/T 38509-2020滑坡防治设计规范
- GB/T 33336-2016高纯工业品三氯氧磷
- FZ/T 07019-2021针织印染面料单位产品能源消耗限额
- 低利率时代家庭财富管理课件
- 舌尖上的台州课件
- 全国硕士研究生入学统一考试英语(二)模拟卷
- 拆除、报废记录表
- 生命密码-课件
- 动画制作员职业技能鉴定考试题库-下(多选、判断题部分)
- 急救中心急救站点建设标准
评论
0/150
提交评论