《程序设计课件-指针.ppt》由会员分享,可在线阅读,更多相关《程序设计课件-指针.ppt(71页珍藏版)》请在三一办公上搜索。
1、指 针,目 录,地址和指针的概念 变量的指针和指向变量的指针变量 数组与指针 字符串与指针 指向函数的指针 返回指针值的函数 指向数组和指向指针的指针 指针的数据类型和指针运算小结,指针的概念,指针是C语言的一个重要概念,也是C语言的一个重要特色。深刻理解和正确使用指针是学习本章的基本要求。,一、地址,在计算机中,把内存区划分为一个一个的存储单元,每个单元为一个字节(位),它们都有一个编号,这个编号就是内存地址。如下图所示:,注意:1、程序中定义的每个变量在编译后都占有各自的内存区,系统通过内存地址对变量进行存取。2、数据所占有的存储单元个数是由其类型决定的。3、首地址:第1个单元的地址4、表
2、示地址的数与整数的区别,指针的概念,二、举例,如有定义:char c=A;int a=3;则所占内存情况如下:,注意:c和a的地址可能相邻,也可能不相邻,由系统分配。,指针的概念,三、指针与指针变量,1、指针:简单地说,指针就是地址。二者是同一个概念的两种说法。只不过指针更形象一些,就像一个针一样,可以指向某个内存单元。,2、指针变量:首先指针变量就是一个变量,和以前所讲的其它变量没有本质区别。不同之处在于这种变量中所存放的内容是地址。,指针的概念,四、直接访问和间接访问,指针的概念,A,B,1、直接访问,通过变量本身对变量进行存取的方式,称为直接访问。如定义:int x;则x=10;x+=5
3、;这种访问方式只需要变量本身就得到了该变量的全部信息,不需要其它内容,是直接的。,指针的概念,2、间接访问,通过指针变量实现对变量的访问方式,称为间接访问。首先要定义一个指针变量,然后将一个同类型变量的地址赋给该指针变量(称指针变量指向该变量),这样就可以进行间接访问了。间接访问的过程是:由指针变量得到变量的地址,根据该地址找到变量的存储区,再对该存储区的内容进行存取,从而实现了对变量的间接访问。,指针的概念,指针变量的定义和引用,一、指针变量的定义和赋值,1、格式:类型名*指针变量名;,2、举例 int*p1;char*s1,*s2;float*a1,*a2,f;,3、说明 a.类型名:指针
4、变量所指向的变量类型。b.*是定义指针变量的标志,不可丢掉。c.指针变量定义后,其值是不确定的。,4、赋值:可以进行初始化,也可以使用赋值语句,(1)、初始化:int a,*s=,(2)、赋值语句 int a,*s;s=,(3)、注意:只能用同类型变量的地址进行赋值 如定义:int*s;float f;则 s=是错误的。,指针变量的定义和引用,不定,在分析有关指针的程序时,画图是很好的方法:,若有:int a,*s;则,s,a,若有:int a=5,*s=则,不定,5,&a,指针变量的定义和引用,二、指针变量的引用,1、两个运算符:&与*&:取地址,注意与作位运算符时的不同(双目)*:指针运算
5、符(间接访问符),取内容,*P表示P所指向的变量,注意与乘运算符不同(双目),2、说明 a.&既可作用于一般变量,也可作用于指针变量 b.*只能作用于指针变量,*s等同于变量a。c.定义指针变量时的*与该处的含义不同,指针变量的定义和引用,3、指针变量可以进行的操作(1)赋值:int a,*p1=(5)比较:一般与指针常量NULL进行比较;两指针 变量值的大小比较无意义。,指针变量的定义和引用,#include main()int a1=11,a2=22;int*p1,*p2;p1=,指针变量的定义和引用,#include main()int a1=11,a2=22;int*p1,*p2,*p
6、;p1=,指针变量的定义和引用,#include main()int a1=11,a2=22,t;int*p1,*p2;p1=,指针变量的定义和引用,三、指针变量作为函数的参数,1、形式:形式参数名前加上一个*。如:void test(int*pointer,char f,char*s),2、说明 通过指针作为参数可以将主调函数中某变量的地址传递到被调函数中,从而可以改变该地址对应变量的值,即改变主调函数中变量的值。,指针变量的定义和引用,指针变量的定义和引用,#include void test(int*pt);main()int a=11,*p=,指针与一维数组,在语言中,指针与数组有着密
7、切的关系。对数组元素,既可以采用数组下标来引用,也可以通过指向数组元素的指针来引用。采用指针方法处理数组,可以产生代码长度小、运行速度快的程序。,一、通过指针访问一维数组,1、数组结构的分析,设有数组定义为:int a5;则有:(1)a表示数组在内存中的首地址,也就是数组中第1 个元素的首地址,它是一个地址常量,其值由系 统在编译时确定,程序运行期间不能改变。(2)数组中的各元素表示为:a0、a1、a2、a3、a4 或者是:*(a+0)、*(a+1)、*(a+2)、*(a+3)、*(a+4),指针与一维数组,(3)数组中的各元素的地址表示为:&a0、&a1、&a2、&a3、&a4 或者是:a+
8、0、a+1、a+2、a+3、a+4(4)另一种解释:数组名是基地址,下标是偏移量,ai就表示以a为基地址,偏移i个元素的那个元素。(5)数组的逻辑结构如下:,a,&a0&a1&a2&a3&a4,指针与一维数组,2、指针与数组的关系,现定义一个指针变量:int*s;并进行赋值:s=a;或 s=则,指针变量s指向了数组a的开始,二者产生了联系,这样就可以通过指针变量s访问数组a了。,a,&a0&a1&a2&a3&a4,s,注意:a是指针常量 s是指针变量,指针与一维数组,对s也可以进行其它赋值,如:s=a+2;或 s=图变为:,a,&a0&a1&a2&a3&a4,s,说明:若进行操作 s=a;s+
9、=2;效果与上述相同。,指针与一维数组,3、一维数组的访问,#include main()int a5=1,3,5,7,9,i,*p=a;for(i=0;i5;i+)printf(“%d”,ai);for(i=0;i5;i+)printf(“%d”,*(a+i);for(i=0;i5;i+)printf(“%d”,pi);for(i=0;i5;i+)printf(“%d”,*(p+i);for(;pa+5;p+)printf(“%d”,*p);p=a;while(pa+5)printf(“%d”,*p+);,指针与一维数组,用多种方法访问一维数组各元素,4、几个表达式的分析,设定义:int a
10、3=1,2,3,*s=a;s,*s a,*a s+,*s+,a+,*a+*(s+),(*s)+*(a+),(*a)+初始化时的*s=a;与语句*s=a;的不同 一个指针变量加/减一个整数后,指针变量值的变化情况,指针与一维数组,二、通过指针在函数间传递一维数组,1、函数的定义形式,int func(int array,int n)函数体;也可以写为:int func(int*pointer,int n)函数体;,指针与一维数组,2、函数的说明形式,如有函数定义:int func(int array,int n)函数体;则对该函数的说明形式可以写为:int func(int array,int
11、n);int func(int*array,int n);int func(int,int);int func(int*,int);,注意:作为形参定义的数组名是一个指针变量,它在函数体中可以变化,这一点与变量定义时不同。,指针与一维数组,编写在数组的最后一个元素中存放其它元素和的函数#include void summary(int*p,int n);main()static int a11=1,2,3,4,5,6,7,8,9,10;summary(a,10);printf(“Sum is%dn”,a10);void summary(int*p,int n)int s=0;while(n)s
12、+=*(p+);*p=s;,指针与一维数组,函数还可写为:void summary(int arr,int n)int i,s=0;for(i=0;in;i+)s+=arri;arrn=s;,字符串是一种特殊的一维数组,字符串的特殊性在于:字符串的末尾是结束标志 0,所以访问字符串时常用结束标志进行判断。,指针与字符串,一、通过指针访问字符串,1、字符串结构的分析,设有数组定义为:char s=“abcde”;则s是一个字符数组,它里面存放的是一个字符串。它在内存中占用6个字节,但长度为5。其结构为:,s,s0 s1 s2 s3 s4 s5,结束标志,指针与字符串,字符串还可以定义为:char
13、*s=“abcde”;它在内存中占用6个字节,长度为5。其结构为:,指针与字符串,s,s0 s1 s2 s3 s4 s5,结束标志,2、用字符数组与用指针使用字符串的比较,定义及初始化char s=“abcde”;char*p=“abcde”;赋值char s6;char*p;s=“abcde”;p=“abcde”;strcpy(s,“abcde”);strcpy(p,“abcde”);使用s不能自加/减 p可以自加/减,指针与字符串,注意:char s=“abc”;与char s=a,b,c;的区别,(2)指针法main()char a=“Hello,world!”;char b20;cha
14、r*pa,*pb;for(pa=a,pb=b;*pa!=0;pa+,pb+)*pb=*pa;*pb=0;printf(“%sn”,b);,该功能相当于:strcpy(b,a);,指针与字符串,下标法 main()char a=“Hello,world!”;char b20;int i;for(i=0;ai!=0;i+)bi=ai;bi=0;printf(“%sn”,b);,将字符数组a中的字符串拷贝到字符数组b中,二、字符串指针作函数参数,1、函数的定义形式,char func(char a,char b)函数体;也可以写为:char func(char*a,char*b)函数体;,指针与字符
15、串,void mystrcpy(char*to,char*from);main()char ca20,*cp=“Hello,world!”;mystrcpy(ca,cp);printf(“%s”,ca);,设计一函数,实现与标准函数strcpy类似的功能。,void mystrcpy(char*to,char*from)while(*from!=0)*to=*from;to+;from+;*to=0;,思考:调用 mystrcpy(ca,cp+2);结果如何?,指针与多维数组,数组是具有相同“数据类型”的数据的顺序集合,而数组本身也是语言的一种数据类型,同样可以作为数组的元素类型。当一个一维数
16、组的元素类型为数组时,便构成了多维数组。熟记下面两组等价式:xi*(x+i)&xi x+i,一、通过指针访问多维数组,1、二维数组结构的分析,设有数组定义为:int a34;则有:a表示数组在内存中的首地址,也就是数组中第1个元素(也是第一行)的首地址,它是一个地址常量,其值由系统在编译时确定,程序运行期间不能改变。该二维数组可以理解为:它是一个一维数组,含有3个元素,每个元素又是一个一维数组,该一维数组含有4个元素,每个元素是int类型。,指针与多维数组,二维数组的逻辑结构图如下:,a0,a1,a2,a+0,a+2,a+1,指针与多维数组,指针与多维数组,2、指向二维数组中一行的指针变量,(
17、1)格式:类型名(*指针变量名)长度;(2)例如:int(*pa)4;(3)含义:pa是指针变量,它指向一个数组,数组 含有4个元素,每个元素的类型是int。(4)说明:a.与定义 int*pa;以及 int*pa4;含义不同。b.如果执行pa+,则pa实际增加了多少呢?,pa实际增加了2*4=8个字节,指针与多维数组,c.若定义:int a34,(*pa)4=a;则关系图为:,a,pa,(*pa)0(*pa)1(*pa)2(*pa)3,如果执行pa+,则变为如图所示,pa,pa,那么(*pa)0、(*pa)1、(*pa)2、(*pa)3 也变了,指针与多维数组,3、几个表达式,由 xi*(x
18、+i)和&xi x+i 可以得出:aij(*(a+i)j*(ai+j)*(*(a+i)+j)&aij*(a+i)+j ai+j,指针与多维数组,例:用各种方法访问二维数组各元素#include main()int aa34=1,2,3,4,5,6,7,8,9,10,11,12;int i,j,*p,(*pa)4;/第一种方法 for(pa=aa,i=0;i3;i+)printf(“n”);for(j=0;j4;j+)printf(“%5d”,paij);,/第二种方法 for(pa=aa;paaa+3;pa+)printf(“n”);for(j=0;j4;j+)printf(“%5d”,(*p
19、a)j);/第三种方法 for(p=aa0;paa0+3*4;p+)printf(“n”);printf(“%5d”,*p);,指针与多维数组,二、通过指针在函数间传递多维数组,1、函数的定义形式,例如:int func(int array4,int n)函数体;也可以写为:int func(int(*pa)4,int n)函数体;,指针与多维数组,2、函数的说明形式,如有函数定义:int func(int array4,int n)函数体;则对该函数的说明形式可以写为:int func(int array4,int n);int func(int(*pa)4,int n);int func(
20、int 4,int);int func(int(*)4,int);,注意:作为形参定义的数组名是一个指针变量,它在函数体中可以变化,这一点与变量定义时不同。,指针与多维数组,例 求3行4列二维数组中的最大元素#include int max_value(int(*pa)4,int row);main()int aa34=1,3,5,7,2,4,6,8,20,15,32,12;printf(“max element is%dn”,max_value(aa,3);int max_value(int(*pa)4,int row)int i,j,m=pa00;for(i=0;im)m=paij;ret
21、urn(m);,指针与多维数组,例 求3行4列二维数组中的最大元素(另一种方法)#include int max_value(int*p,int n);main()int aa34=1,3,5,7,2,4,6,8,20,15,32,12;int max=max_value(,指针与多维数组,指针数组与指向指针的指针,一、指针数组,1、指针数组的概念,指针数组是一种特殊的数组,它每个元素的类型都是指针类型(即地址),其它与一般数组相同。当把某个量的地址放入某元素中后,即可通过该元素对相应的量进行间接访问。,2、指针数组的定义,类型名*指针数组名常量表达式;如:int*ap3;char*s10;,
22、3、指针数组的初始化,(1)int a15,a25,a35,*ap3=a1,a2,a3;(2)char*sp=“abc”,“123”,“Hello”;,4、指针数组的赋值,上面的情况中,可以先定义变量,再进行赋值,即(1)int a15,a25,a35,*ap3;ap0=a1;ap1=a2;ap2=a3;(2)char*sp=“abc”,“123”,“Hello”;sp0=“abc”;sp1=“123”;sp2=“Hello”;,指针数组与指向指针的指针,例:显示多个字符串void main()/指针数组实现 char*ap3=“CPU”,“Computer”,“Microprocessor”
23、;for(int i=0;i3;i+)puts(api);void main()/二维字符数组实现 char aa315=“CPU”,“Computer”,“Microprocessor”;for(int i=0;i3;i+)puts(aai);,指针数组与指向指针的指针,两种方法中所占内存空间的比较,aa0,aa1,aa2,ap,指针数组与指向指针的指针,二、指向指针的指针,2、多级指针的定义,类型标识符*指针变量名;注:*的个数代表级数(要求掌握到二级即可)如:char*pp,*p,ch=A;又p=则:,1、多级指针的概念,所谓多级指针,是指指针有多级指向关系。,&p,&ch,A,pp,p
24、,ch,指针数组与指向指针的指针,3、多级指针的含义,若定义:char*ps=“abc”,“123”,*pp=ps;则:*pp 为“abc”*(pp+1)为“123”*(*(pp+1)+2)为 3执行 pp+;则:*pp 为“123”,指针数组与指向指针的指针,例:显示并选择菜单条目#include int getchoice(char*menu,int n);void main()int chc;static char*mn5=“1.Input”,“2.Copy”,“3.Move”,“4.Delete”,“0.Exit”;chc=getchoice(mn,5);if(chc=0,指针数组与指
25、向指针的指针,int getchoice(char*menu,int n)int i,choice;for(i=0;in;i+)puts(*(menu+i);printf(“nInput your choice:”);return(getchar()-0);,指针数组与指向指针的指针,三、命令行参数,1、命令行参数的概念,1)DOS命令:copy file1 file2 2)以前的main函数形式:main()3)mian函数的调用由系统完成 4)带参main函数:main(int argc,char*argv);或 main(int argc,char*argv);或 main(int ar
26、gc,char argv);,指针数组与指向指针的指针,2、命令行参数的说明,1)形参也可以用其它名字,习惯上为argc和argv 2)argc和argv的值的获得 如有程序myprog.c,经编译和链接生成可执行程序myprog.exe,在命令行中输入:myprog argument1 argument2则 argc的值为3,argv0的值为“myprog”,argv1的值为“argument1”,argv2的值为“argument2”。3)实现:DOS提示符状态下或集成环境中。,指针数组与指向指针的指针,例 输出各命令行参数#include main(int argc,char*argv)
27、int i;for(i=1;iargc;i+)printf(“arg%d:%sn”,i,argvi);若可执行文件为showarg,运行时键入:showarg Computer and C language则输出为:arg1:Computer arg2:and arg3:C arg4:language,指针数组与指向指针的指针,返回指针值的函数,1、概念,当函数的返回值是指针类型(地址)时,则称为指针函数。,2、定义,类型名*函数名(形参表);如:int*f(int a);,如:char*gets(char*buffer);功能:从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将
28、读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。,例 将一个字符串转换为大写形式并输出#include char*mytoupper(char*s);main()char ps80,*s;gets(ps);s=mytoupper(ps);puts(s);char*mytoupper(char*s)char*t=s;while(*t!=0)*t=(*t=a,返回指针值的函数,指向函数的指针,1、函数名的含义,函数名代表函数的入口地址,即函数代码在内存中的起始位置。,2、概念,如果一个指针指向一个函数,则称该指针为函
29、数指针。(注意与指针函数的区别),3、定义,类型名(*指针变量名)(形参表);如:int(*f)(int a,int b);,例 函数指针举例#include int max(int a,int b);int min(int a,int b);main()int x=3,y=4,z;int(*pf)(int,int);pf=max;z=(*pf)(x,y);printf(max is%dn”,z);pf=min;printf(“min is%dn,(*pf)(x,y);,指向函数的指针,int max(int a,int b)return(ab?a:b);int min(int a,int b
30、)return(ab?a:b);,动态内存分配,由变量的作用域和存储类别知道,内存变量都有生存期,以前接触的变量,其内存的分配及释放都是由系统统一管理的。这一节我们介绍如何实现自己对变量空间的申请和释放。动态内存分配可以提高内存的使用效率。,1)void*malloc(unsigned int size);该函数实现对内存的申请,申请大小为size,返回值为指针类型,指向所申请空间的首地址。2)void*calloc(unsigned n,unsigned size);在内存动态存储区分配n个长度为size的连续空间3)void free(void*block);该函数实现对由malloc函数
31、申请到的内存的释放4)void*realloc(void*p,unsigned int size);将p所指向的动态空间大小改变为size5)void exit(int status);该函数终止程序的执行。说明:这5个函数都在头文件stdlib.h中。,动态内存分配(使用的函数),调用形式:(类型说明符*)malloc(size)功能:在内存的动态存储区中分配一块长度为size字节的连续区域。函数返回值为该区域的首地址。“类型说明符”表示把该区域用于何种数据类型。(类型说明符*)表示把返回值强制转换为该类型指针。“size”是一个无符号数。例如:pc=(char*)malloc(sizeof
32、(char);强制转换为字符数组类型,函数的返回值为指向该字符数组的指针,把该指针赋予指针变量pc。,分配内存空间函数malloc,调用形式:(类型说明符*)calloc(n,size)功能:在内存动态存储区中分配n块长度为“size”字节的连续区域。函数的返回值为该区域的首地址。例如:ps=(char*)calloc(2,sizeof(char);按char的长度分配2块连续区域,强制转换为char类型,并把其首地址赋予指针变量ps。,分配内存空间函数 calloc,调用形式:free(void*ptr);功能:释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量,它指向被释放区域
33、的首地址。被释放区应是由malloc或calloc函数所分配的区域。,释放内存空间函数free,2、实现方法,1)包含头文件:#include 2)定义变量:类型名*指针变量名;如 int*s;3)申请内存:s=(int*)malloc(n*sizeof(int);4)检测:if(s=NULL)exit(1);5)使用:for(i=0;in;i+)si=i;6)释放:free(s);,动态内存分配,#include#include void main()void check(int*)int*p1,i;p1=(int*)malloc(5*sizeof(int);for(i=0;i5;i+)scanf(“%d”,p1+i);check(p1);,动态内存分配,void check(int*p)int i;printf(“They are fail:”);for(i=0;i5;i+)if(pi60)printf(“%d”,pi);printf(“n”);,本章要点小结,1)几种指针的定义格式及含义(1)char*p;/*一般指针*/(2)char(*pa)N;/*数组指针*/(3)char*paN;/*指针数组*/(4)char*pp;/*二级指针*/(5)char*fp();/*指针函数*/(6)char(*pf)();/*函数指针*/2)正确读指针的方法3)指针与数组,