C语言第08章 指针_第1页
C语言第08章 指针_第2页
C语言第08章 指针_第3页
C语言第08章 指针_第4页
C语言第08章 指针_第5页
已阅读5页,还剩60页未读 继续免费阅读

下载本文档

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

文档简介

1、指 针编辑课件第7章 指针第一节 地址和指针的概念第二节 变量的指针和指针变量第三节 数组指针第四节 字符串指针第五节 函数指针第六节 返回指针的值第七节 指针数组第八节 小结2编辑课件第7章 指针指针是C语言中的一个重要的概念,正确而灵活地运用它,可以有效地表达复杂的数据结构;能动态分配内存;能方便地使用字符串、数组、函数;能直接处理内存地址。可以说,不掌握指针就不掌握C语言。3编辑课件 两个概念内存单元: 程序中定义的每个变量,都在内存中占有一定的空间,称为内存单元。内存单元地址: 内存区的每一个字节有一个编号,称为内存地址。7-1地址和指针的概念4编辑课件 例如程序定义了三个变量:Int

2、 a,b,c;则系统给出三个单元: 地址1 地址2 地址37-1地址和指针的概念a b c 5编辑课件实际上一个变量有三个值:地址、变量名、值。例:Int a=3,b=7,c=9; 地址 变量名 值 地址1 地址2 地址37-1地址和指针的概念 a 3 b 7 c 9 6编辑课件内存单元的大小:程序中不同类型的变量,大小也不一样。 *实型变量:占有 4 个字节。 *整型变量:占有 2 个字节。 *字符变量:占有 1 个字节。注:1个字节为8位: 7-1地址和指针的概念 7 6 5 4 3 2 1 07编辑课件 例:程序定义了3个整型 内存用户数据区变量i、j、k,编译时系统分配置2000和20

3、01两个字节给变量i,2002和2003字 2000 3 变量i 节给j,2004,20005给k。 2002 6 变量j则有:变量 开始地址 2004 9 变量k i 2000 . j 2002 . k 2004 3010 2000 i-pot 单元内的内容就是变量的值 7-1地址和指针的概念8编辑课件 对变量的存取是通过地址 内存用户数据区来进行。如果语句中有:“k=i+j”,则从2000、2001字节取出I值(3),再从 2000 3 变量i 2002,2003字节取出j值 2002 6 变量j(6),相加后得(9), 2004 9 变量k 送给k所占的2004, . 2005单元。 .

4、 这种存取方式称为 3010 2000 i-pot “直接访问:方式。 7-1直接访问方式9编辑课件 也可以采用另一种存取方式, 内存用户数据区变量I的地址存放在另一个变量Ipot中,即:Ipot=&I;这样,Ipot的值就是2000, 2000 3 变量i 即变量I的起始地址。要存 2002 6 变量j取I的值,也可以从变量 2004 9 变量kIpot中取出I的地址(2000) .然后到2000,2001处取出 .I的值(3)。 3010 2000 ipot 这种存取方式称为 :“间接访问:方式 7-1间接访问方式10编辑课件7-2地址和指针的概念*什么叫做指针?举两个日常例子:(1)每个

5、同学的记分表都有这三栏: 编 号 姓 名 分数 1001 王 刚 70 1002 李 鹏 78 1003 张 三 92那么,要对某个同学记分和查分都是通过编号进行,编号就是姓名的指针。11编辑课件指针: 由于通过地址能找到所需的变量单元,我们称一个变量的地址为该变量的指针。 地址1(指针1) 地址2(指针2) 地址3(指针3)7-1地址和指针的概念 a 3 b 7 c 9 12编辑课件指针变量: 一个变量,是用来存放另一个变量的地址,则它称为指针变量。地址和指针的概念13编辑课件指针变量的定义格式 基本类型 *指针变量名例: float *p1; /*实型指针*/ int *p2; /*整型指

6、针*/ char *p3; /*字符指针*/注意 “*”号 不能省略。7-2-1定义一个指针变量14编辑课件例:通过指针变量的赋值。必须在变量面前加上地址赋值符号:“&”Main()int a,*p1; float b,*p2; char c,*p3;a=100;b=3.12; c=k;p1=&a; /*变量a的地址赋给指针p1*/p2=&b; /*变量b的地址赋给指针p2*/p2=&b; /*变量c的地址赋给指针p3*/7-2-2指针变量的引用15编辑课件指针变量的使用。如果有:int a,*p1; a=100; p1=&a; /*变量a的地址赋给指针p1*/则我们用符号: *p1表示所指变

7、量a。 即 *p1=100;7-2-2指针变量的引用16编辑课件同样有:Float b,*p2; b=3.12; p2=&b; /*变量b的地址赋给指针p2*/则我们用符号: *p2表示所指变量b。 即 *p2=3.12;7-2-2指针变量的引用17编辑课件因此,只要有:Float b,d,*p2; p2=&b; /*变量b的地址赋给指针p2*/ p2=3.12; 则在程序内,这两条语句是等价的: d=b; d=*p;7-2-2指针变量的引用18编辑课件例:通过指针变量访问整形变量。Main()int a,b,*p1,*p2;a=100;b=10;p1=&a; /*变量a的地址赋给指针p1*/

8、p2=&b; /*变量b的地址赋给指针p2*/Printf(“%d,%dn”,a,b);Printf(“%d,%dn”,*p1,*p2);结果为: 100,10 100,10 7-2-2指针变量的引用19编辑课件注意:(1)指针变量前面的“*”, 表示该变量的类型为指针 型变量。(2)在定义指针变量时必 须指定基本类型 原因是:单位字节数不同。 实型指针变量一个单位是 4个字节。 型型指针变量一个单位是 2个字节。 字符型指针变量一个单位是 1个字节。指针变量的赋值 point-2=&f; /*实变量f的地址赋给指针*/ point-3=&I; /*整变量i的地址赋给指针*/ point-4=

9、&a; /*字符变量a的地址赋给指针*/7-2-1定义一个指针变量2000200120022003200420052006实变量f型变量i字符a20编辑课件例:输入a,b两个整数,按先大后小输出a和b。Main()int a,b,*p1,*p2;Scanf(“%d,%d”,&a,&b);p1=&a; /*变量a的地址赋给指针p1*/p2=&b; /*变量b的地址赋给指针p2*/If(ab) p=p1;p1=p2;p2=p;Printf(“na=%d,b=%dn”,a,b);Printf(“max=%d,min=%dn”,*p1,*p2);输入 5,9 结果为: a=5,b=9 max=9,mi

10、x=57-2-2指针变量的引用21编辑课件当输入a=5,b=9时,由于ab,将p1和p2交换。如图:注意:a和b并未交换,但p1和p2的值改变了。P1的为&a,现为&b,p2原为&b,现为&a。7-2-2指针变量的引用p&b&ap2ap1p9b5bap2p19&a&b22编辑课件函数的参数不仅可以是整型、实型、 字符型等,还可以是指针型。指针变量作为函数参数的作用是:将一个变量的地址传送到另一个函数中。再举上例:输入a,b两个整数,按先大后小输出a和b。7-2-3指针变量作为函数参数23编辑课件main()int a,b,*t1,*t2;scanf(“%d,%d”,&a,&b);t1=&a;

11、/*变量a的地址赋给指针t1*/t2=&b; /*变量b的地址赋给指针t2*/If(ab) sw(t1,t2); /*调用函数sw,其中t1,t2为指针变量*/Printf(“na=%d,b=%dn”,a,b);7-2-3指针变量作为函数参数24编辑课件子函数 sw 的作用是交换两个变量a和b的值。Sw(int *p1,int *p2)int temp; temp=*p1; *p1=*p2; *p2=temp; 运行情况如下:输入: 5,9结果: 9,57-2-3指针变量作为函数参数25编辑课件当t1=&a,t2=&b时 当调用sw(t1,t2)时如图:7-2-3指针变量的引用&b&ap2ap

12、19b5bap2p19&a&b&b&at1t226编辑课件当执行函数sw(t1,t2)时 当返回主函数时7-2-3指针变量的引用&b&at2at19b5bap2p19&a&b&b&at1t25函数调用结束后,p1和p2不复存在(已释放)27编辑课件数组与指针的关系每一个数组元素都有地址。该地址就是数组元素的指针。概念假设:int a100;数组名:数组的标识 a数组元素的地址:数组中一个具体元素的地址(&ak)数组首地址(数组起始地址):数组中第一个元素(0号元素)的地址(&a0或用数组的名称 a 表示)。7-3数组与指针28编辑课件C语言规定:数组名就是数组的首地址常量。那么下面关系表达式成

13、立:a = &a0例: int a10; /*定义a为整型数组*/ int *p; /*定义p为整 型指针变量*/ p=&a0; 将第一个元素的地址赋给p,实际上是首地址赋给p。与下条语句等价: p=a p就称为指向数组a的指针变量。指向数组的指针&a0a029编辑课件C语言规定:如果指针变量p已指向数组中的一个元素, 则p+1指向同一数组中的下一个元素。 例如: int a4,*p; p=&a0; 则: p+1 a1 p+2 a2 p+3 a37-3指向数组的指针注:这里的p+1是指加上一个单元, 不同的变量,单元的大小不同。 整型指针变量p+1等于p的地址 加上2个字节。 p+2=p+4个

14、节。 (实型: p+1=p+4个字节。 字符型: p+1=p+1个字节。30编辑课件例C5_5001.C:分析程序。 #include main ( )int a = 1, 2, 3, 4, 5 ;int x, y, *p; /* 指针变量 p */p= &a0;x= *(p+2); y= *(p+4); printf (*p=%d, x=%d, y=%dn, *p, x, y);7-3数组与指针例C5_5001/* 指针 p 指向 a0,等价于p=a */* 取指针p+2的内容,等价于x=a2 */* 取指针p+4的内容,等价于y=a4 */指针方式数组a*(p)=1*(p+1)=2*(p+

15、2)=3*(p+3)=4*(p+4)=5&a0pp+2p+4下标方式a2a1a0a3a4指针方式数组a*(a+0)=1*(a+1)=2*(a+2)=3*(a+3)=4*(a+4)=5aa+2a+431编辑课件例C5_5002.C:分析程序。main( )int a = 1, 2, 3, 4, 5, 6 ;int *p; p=a; /* 指针p为数组的首地址 */printf (%d, *p );printf ( %dn, *(+p) ); printf (%d, *+p );printf ( %dn, *(p-) );p += 3;printf(%d %dn, *p, *(a+3) );7-3

16、 数组与指针例C5_5002指针初始化第一个输出第二个输出第三个输出第四个输出第五个输出p=a取p的内容p先加1再取内容p先加1再取内容取内容p再减1取p的内容p+=3pppppp12指针初始化345aa+1a+2a+3a+4a0a1a2a3a4语句执行指针p指向地址数组32编辑课件在函数之间传递整个数组实际参数用数组名。形式参数用指针时,在被调用函数的内部,就可用指针方式访问数组中的元素。说明由于数组名代表数组的首地址,传递数组名也就是将数组的首地址传递给被调用函数。7-3-3 数组名作为函数33编辑课件例:编写字符串复制函数。main( )char a30, b30;printf(Ente

17、r string:);scanf (%s, a);strcopy ( a, b ); /* 调用函数的实参为数组名 */printf (a=%snb=%sn, a, b );strcopy ( str1, str2 )/* 将串str1拷贝到串str2中 */ char * str1, * str2;/* 形参为指向字符的指针 */while ( (*str2 = *str1)!=0)/* 通过指针操作数组 */str1+; str2+;5-5 数组与指针-串复制7-3 数组与指针-串复制例C5_500334编辑课件例:改进字符串复制函数。改进一:strcopy ( str1, str2 )

18、char *str1, *str2;while ( *str2 = *str1 ) str1+; str2+;改进二:strcopy ( str1, str2 ) char *str1, *str2; while ( *str2+ = *str1+ ) ; /* 通过指针操作数组 */7-3数组与指针-串复制例C5_50031例C5_5003235编辑课件对于指针的三种基本运算指针与正整数的加减运算两个指针的关系运算两个指针的减法运算与指针相关的运算操作取地址运算 ( & )取内容运算 ( * )7-3指针的基本运算36编辑课件指针与正整数的加减法当指针 p 指向数组中的元素时,n为正整数:

19、p+n表示:指针p所指向当前元素之后的第n个元素; p-n表示:指针p所指向当前元素之前的第n个元素。 p+和+p含义:指针加1,指向数组中的下一个元素; p-和-p含义:指针减1,指向数组中的前一个元素。7-3 指针的基本运算-指针加减运算p-2p-1pp+1p+2.p-3.数组低地址高地址37编辑课件设 int b,c,d,e,a4; p=&a0; a0=3; 则:b=*(p+); 表示先取*p值,即b=a0 后p加1 而 c=*(+p); 表示p先加1,后取c=*(p+1) 即 c=a1 d=(*p)+; 相当于 d=a0+, 先取a0=3 赋给d,后a0=a0+1等于4。 e=+(*p

20、); 相当于 e=+a0, 先取a0=a0+1 等于4,后 赋给d。7-3指针的基本运算38编辑课件回忆! 对于一个字符串,我们是如何访问? 方法:用字符数组。例: main() int I; char st6=“china”; for ( I=0;I=5;I+) printf(“%c”,aI); 结果输出:china7-4字符串的指针和指向字符串的的指针变量39编辑课件也可以用字符指针来访问一个字符串。 例: main() char *sp 定义指针变量 sp=“china”; 表示将字符串 printf(“%sn”,sp; “china”的首 结果输出:china 地址赋给sp 7-4字符

21、串的指针和指向字符串的的指针变量40编辑课件例:将字符串a复制为字符串b。 main() int j; char a=“china”,b5,*p,*q; p=a; for (j=0;j=5;j+) *(q+j)=*(p+j); 指针改变数组b的值 printf(“n%s”,p); for(j=0;j=5;j+) printf(“n%c”,bj); 结果: china china 7-4字符串的指针和指向字符串的的指针变量41编辑课件上例也可改为: main() int j; char a=“china”,b5; for (j=0;j=5;j+) *(b+j)=*(a+j); 指针改变数组b的值

22、 printf(“n%s”,a); for(j=0;j=5;j+) printf(“n%c”,bj); 结果: china china 7-4字符串的指针和指向字符串的的指针变量42编辑课件前面介绍过,字符数组和字符指针都能实现字符串的存储和运算。但它们两者是有区别(1)字符数组由若干个元素组成,每个元素放一个字符。 字符指针变量中存放的是地址-字符串的首地址。而不是将字符串放到字符指针变量中 7-4-3对使用字符指针变量和字符数组的区别43编辑课件(2)赋值方式。对字符数组只能对各个元素赋值,不能如下赋值:Char st5;St=“china”; 而字符指针变量中,可以这样做:Char *s

23、p sp=“china”;注意:sp存放的是字符串的首地址。 7-4-3对使用字符指针变量和字符数组的区别44编辑课件 例C5_5004.C:使用指针作为形式参数实现函数day_of_year。#include main( )static int day_tab213 = 0,31,28,31,30,31,30,31,31,30,31,30,31, 0,31,29,31,30,31,30,31,31,30,31,30,31 ;int y, m, d;scanf(%d%d%d, &y, &m, &d);printf(“%dn”, day_of_year(day_tab,y,m,d) ); day

24、_of_year ( day_tab, year, month, day) int * day_tab; int year, month, day; int i, j; i = ( year%4=0 & year%100!=0 ) | year%400=0; for ( j=1; jmonth; j+ ) day+= *(day_tab+i*13+j); /*通过指针访问数组元素*/ return(day);7-4 数组与指针-用指针操作二维数组例C5_500445编辑课件指针数组数组中的元素均为指针类型,称之为指针数组。指针数组说明的形式为:数据类型 * 数组名常量表达式例如: int *

25、pa 6;含义:定义一个由6个指针变量构成的指针数组,数组中的每个数组元素指针,都指向一个整数。7-5 指针数组整数整数整数整数整数整数pa0pa1pa2pa3pa4pa5指针数组pa46编辑课件数组指针指向数组的指针称为数组指针。数组指针的说明形式:数据类型 ( * 指针变量名)常量表达式例如:int ( * pb ) 6;含义:定义了一个指向数组的指针pb,被指向的数组是一维的有6个元素的整型数组。7-5 指针数组整数整数整数整数整数整数(*pb)0(*pb)1(*pb)2(*pb)3(*pb)4(*pb)5pb47编辑课件例C5_7101.C:将C5_3002.C中的week_day表用

26、指针数组实现。char * week_day8= sunday,monday,tuesday,wednesday,thursday,friday,saturday,NULL;7-5 指针数组-输入字符串进行查找sunday0monday0tuesday0friday0thursday0saturday0wednesday0数组week_dayweek_day0week_day1week_day2week_day3week_day4week_day5week_day6week_day7NULL48编辑课件main函数的参数main函数参数的一般形式: main ( argc, argv ) in

27、t argc; /* argc表示命令行参数个数 */ char *argv ; /* argv指向命令行参数的指针数组 */ 在操作系统下运行C程序时,可以使用命令行参数形式,向main函数传递参数。命令行参数的一般形式:运行文件名参数1参数2参数n.argv0argv1argv2.argvargc-1文件名第1个参数第2个参数.第argc-1(n)个参数数组argv5-7 指针数组-main函数参数argc=n+149编辑课件例C5_7201.C:按数组方式引用命令行的参数。 #include main (argc, argv) int argc; char * argv ; int i;

28、 printf (argc=%dn, argc); for ( i=0; iargc; i+ ) printf(”%sn”, argvi); /* 按数组方式引用参数 */5-7 指针数组-main函数参数实例例C5_7201例C5_7202.C:按指针方式引用命令行的参数。#include main (argc, argv)int argc;char * argv ;int i;for (i=0; iargc; i+) printf(”%sn”, * argv + ); /* 按指针方式引用参数 */例C5_720250编辑课件有关指针的数据类型和指针运算小结int * p;int * q4

29、;int (* w)4;int * g( );int (* y)( );p 是一个指向整型数据的指针变量根据优先级,q先和结合,所以 q 是一个指针数组,该数组有4个元素。( )内的*w指示出w是一个指针,指向一个含4个元素的一维数组。w是数组指针。根据优先级,g先和( )结合,所以 g 是一个函数,*说明函数的返回值是指向整型数据的指针。(*y)说明y是一个指针,( )表明此指针是指向函数的,函数的返回值是整型。51编辑课件指向多维数组的指针变量小结多维数组名的性质 多维数组名是数组的首地址。例如:int a34; a是数组的首地址。 那么,a0、a1、a2 呢? 也是地址量。 把二维数组名

30、,理解成下面的图。a00a10a20a01a11a21a02a12a22a03a13a23aa0a1a2aa00a10a20a01a11a21a02a12a22a03a13a2352编辑课件?指向多维数组的指针变量小结a 、 a0 是 a00的地址,是第一行的首地址。a00a10a20a01a11a21a02a12a22a03a13a23a0a1a2aa+1、a1是 a10的地址,是第二行的首地址。* a是a0的内容,* * a 是 a00。a 是二维数组,经过两次操作,才能访问到数组元素。 所以根据C的地址计算方法,a经过两次 * 操作才能访问到数组元素。这样有: * a是 a0的内容,*

31、* a 才是 a00。 a0是a00的地址,*a0是a00的内容。53编辑课件指向多维数组的指针变量小结例C5_901 已知 int a34=1,2,3,4,5,6,7,8,9,10,11,12; 求: A) *(a+6) B) *(&a0+6) C) *(a1+=2) D) *(&a00+6)例C9_303指到数组元素之后第6个指到数组元素之后第6个a1是地址常量不能赋值指向a12例C5_90154编辑课件申请内存函数 (malloc)void * malloc ( unsigned size )功能:申请长度为size字节的内存区。若申请成功,函数返回所分配的内存区首字节的地址,即指向该内

32、存的指针;若申请失败,函数返回NULL。说明:函数malloc的返回值为指向void类型的指针。这是通用指针类型,在实际申请内存空间时,要按照实际指针所指对象的类型进行指针类型强制转换。实例:要申请1个长度为10的整型数组空间,用指针指向数组的首地址,则可使用下列语句动态申请内存空间。 int * p; p = (int *) malloc( 10 * sizeof(int ) );5-8 动态存储分配函数-malloc55编辑课件释放内存 (free)void free ( void * p )功能:释放p所指的内存空间。函数无返回值。这里p所指的内存区域必须是用函数malloc申请的内存空

33、间,否则调用时使用其它指针,可能会破坏系统。例C5_8001.C:动态申请10个元素的数组。#include main ( )int *p;p = (int *) malloc( 10 * sizeof(int) );printf(“nResult:”); try ( p, 10);free(p);try ( int a , int m ) /* 以数组方式使用主函数空间 */int k;for ( k=0; km; k+ )a k = k*10;for ( k=0; km; k+ )printf (“%d,”, ak);5-8 动态存储分配函数-free例C5_800156编辑课件例C5_5

34、003.C:编写字符串复制函数。main( )char a30, b30;printf(Enter string:);scanf (%s, a);strcopy ( a, b ); /* 调用函数的实参为数组名 */printf (a=%snb=%sn, a, b );strcopy ( str1, str2 )/* 将串str1拷贝到串str2中 */ char * str1, * str2;/* 形参为指向字符的指针 */while ( (*str2 = *str1)!=0)/* 通过指针操作数组 */str1+; str2+;5-5 数组与指针-串复制例C5_500357编辑课件例C5_

35、50031.C:改进字符串复制函数。改进一:strcopy ( str1, str2 ) char *str1, *str2;while ( *str2 = *str1 ) str1+; str2+;改进二:strcopy ( str1, str2 ) char *str1, *str2; while ( *str2+ = *str1+ ) ; /* 通过指针操作数组 */5-5 数组与指针-串复制例C5_50031例C5_5003258编辑课件 例C5_5004.C:使用指针作为形式参数实现函数day_of_year。#include main( )static int day_tab213

36、 = 0,31,28,31,30,31,30,31,31,30,31,30,31, 0,31,29,31,30,31,30,31,31,30,31,30,31 ;int y, m, d;scanf(%d%d%d, &y, &m, &d);printf(“%dn”, day_of_year(day_tab,y,m,d) ); day_of_year ( day_tab, year, month, day) int * day_tab; int year, month, day; int i, j; i = ( year%4=0 & year%100!=0 ) | year%400=0; for ( j=1; jmonth; j+ ) day+= *(day_tab+i*13+j

温馨提示

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

评论

0/150

提交评论