Presentation is loading. Please wait.

Presentation is loading. Please wait.

C语言程序设计 第8章 指针.

Similar presentations


Presentation on theme: "C语言程序设计 第8章 指针."— Presentation transcript:

1 C语言程序设计 第8章 指针

2 第8章 指针 主要内容 8.1 概述 8.2 指针变量的定义和使用 8.3 数组与指针 8.4 指针作为函数的参数
第8章 指针 主要内容 8.1 概述 8.2 指针变量的定义和使用 8.3 数组与指针 8.4 指针作为函数的参数 8.5 指针函数和指向函数的指针变量 8.6 动态内存管理

3 8.1 概述 8.1.1 指针和指针变量 8.1.2 直接访问数据和间接访问数据

4 8.1.1 指针和指针变量 指针 每一个变量,计算机都指定一段内存用以存储变量值。变量使用的这段内存的开始地址,我们称之为变量的地址。在C语言中,通常把变量的地址称为指针。简单的说,指针就是变量的地址。 指针变量 专门用来保存指针的一类变量,它的值是其他变量的地址。指针变量是指向其他变量的变量,通过指针变量就可以实现对其他变量的访问。 指针变量可以指向任何一种数据类型,如可以指向基本类型的变量,也可以指向数组、结构体、共用体以及另外的指针等。

5 8.1.2直接访问数据和间接访问数据 直接访问数据是指通过变量名直接使用变量数据。 例如: int a=10,b=20,c; c=a+b;
printf("%d\n",c); 间接访问数据是指通过指针变量去访问其他变量数据。

6 8.2指针变量的定义和使用 8.2.1 指针变量的定义 8.2.2 指针变量的赋值 8.2.3 指针运算符

7 8.2.1 指针变量的定义 一般格式: 数据类型 *指针变量名1,*指针变量名2,┅; 例如:int *p1,*p2; float *q;
指针变量允许和其他变量同时定义: char ch,*str; 注意: “数据类型”是指针变量要指向的变量的数据类型。

8 8.2.2 指针变量的赋值 (1)初始化方式 一般格式: 数据类型 *指针变量名1=地址1,*指针变量名2=地址2,┅; 例如:int m;
int *p=&m; p m &m (2)先定义变量,再赋值 一般格式: 指针变量=变量地址; 例如:int m=196,*p,*q; p=&m; q=p; p 196 &m q

9 8.2.3 指针运算符 “*”运算符两种作用 在定义指针时是用来说明指针变量 在使用指针进行运算的时,它表示取该指针指向的单元的值。

10 8.2.3 指针运算符 例8-1 使用指针变量的程序示例。 main() {int a,b; int *p1,*p2;
p1=&a; p2=&b; printf("%d,%d\n",a,b); printf("%d,%d\n",*p1,*p2); } a p1=&a; p1 b p2=&b; p2

11 8.2.3 指针运算符 例8-2 输入a和b两个整数,然后按先大后小的顺序输出。 main() { int *p1,*p2,*p,a,b;
scanf("%d,%d",&a,&b); p1=&a; p2=&b; if(a<b) { p=p1; p1=p2; p2=p; } printf("a=%d,b=%d\n",a,b); printf("Max=%d,Min=%d\n",*p1,*p2); }

12 8.2.3 指针运算符

13 8.3 数组与指针 8.3.1 一维数组与指针 8.3.2 二维数组和指针 8.3.3 指针和字符串 8.3.4 指针数组

14 8.3.1 一维数组与指针 要解决的问题 用指针实现一维数组的数据处理 主要内容 如何把一个指针和一维数组关联起来,即怎样使指针指向一维数组
如何使用指针访问一维数组的元素

15 8.3.1 一维数组与指针 定义指向一维数组的指针变量 int a[5]={10,20,30,40,50},*p; p=&a[0];
也可以直接使用数组名为指针变量赋值: p=a; P+1 P+2 P+3 P+4 用指针p访问数组元素 当p指向a[0]后 p与&a[0]等价,*p与a[0]等价; p+1与&a[1]等价,*(p+1)与a[1]等价; p+i与&a[i]等价,*(p+i)与a[i]等价; 也可以使用带下标的指针变量表示数组元素: p[i]与a[i]等价,也与*(p+i)等价。

16 三、一维数组与指针 例8-3 用指针实现一维数组的输入输出。 程序1 程序2 main() main() {int a[5];
int *p=a,i; for(i=0;i<5;i++) scanf("%d",p+i); printf("%d",*(p+i)); } 程序2 main() {int a[5]; int *p=a,i; for(i=0;i<5;i++) scanf("%d“,p++); p=a; printf("%d",*(p+i)); }

17 三、一维数组与指针 产生随机住的程序段 int a[N],i,j,temp,*p; printf("data: ");
例8-4 用指针编写一维数组的排序程序,其中排序数据由随机数函数生成。 产生随机住的程序段 int a[N],i,j,temp,*p; printf("data: "); for(p=a;p<a+N;p++) { *p=rand()%100; printf("%4d",*p); } 完整程序

18 8.3.2 二维数组和指针 要解决的问题 用指针实现二维数组的数据处理 主要内容 如何把一个指针和二维数组关联起来,即怎样使指针指向二维数组
如何使用指针访问二维数组的元素

19 8.3.2 二维数组和指针 回顾二维数组的存储 int a[3][4]; 问题 如何使p指向首元素? a[i][j]的指针如何表示? 10
20 a[0][1] 30 a[0][2] 40 a[0][3] 80 a[1][0] 70 a[1][1] 60 a[1][2] 50 a[1][3] 18 a[2][0] 27 a[2][1] 36 a[2][2] 45 a[2][3] p 回顾二维数组的存储 p+1 p+2 p+3 p+4 p+5 p+6 p+7 p+8 p+9 p+10 p+11 int a[3][4]; 10 20 30 40 80 70 60 50 18 27 36 45 问题 如何使p指向首元素? a[i][j]的指针如何表示?

20 8.3.2 二维数组和指针 指针和二维数组元素的对应关系 设p是指针变量,若有: p=a[0];
则p+j将指向a[0]数组中的元素a[0][j]。 由于a[0]、a[1]、┅、a[M-1]等各个行数组依次连续存储,则对于a数组中的任一元素a[i][j],指针的一般形式如下: p+i*N+j 元素a[i][j]相应的指针表示为:*( p+i*N+j) a[i][j]也可用指针下标法表示:p[i*N+j]

21 8.3.2 二维数组和指针 举例 int a[3][4]={{10,20,30,40,},{50,60,70,80},{90,91,92,93}}; int *p=a[0]; 则数组a的元素a[1][2]对应的指针为: p+1*4+2 元素a[1][2]也就可以表示为:*( p+1*4+2) 用下标表示法,a[1][2]表示为:p[1*4+2]

22 8.3.2 二维数组和指针 用二维数组名表示数组元素 对于二维数组a,其a[0]数组由a指向,a[1]数组则由a+1指向,a[2]数组由a+2指向,以此类推,a[i]数组则由a+i指向。因此,*a与a[0]等价、*(a+1)与a[1]等价、*(a+2)与a[2]等价,┅,*(a+i)与a[i]等价。由此,对于数组元素a[i][j],用数组名a的表示形式为: *(*(a+i)+j) 指向该元素的指针为: *(a+i)+j

23 8.3.2 二维数组和指针 例8-5 求二维数组元素的最大值。 main() {
int a[3][4]={{3,17,8,11},{66,7,8,19},{12,88,7,16}}; int *p,max; for(p=a[0],max=*p;p<a[0]+12;p++) if(*p>max) max=*p; printf("MAX=%d\n",max); }

24 8.3.2 二维数组和指针 例8-6 求二维数组元素的最大值,并确定最大值元素所在的行和列。 main() {
int a[3][4]={{3,17,8,11},{66,7,8,19},{12,88,7,16}}; int *p=a[0],max,i,j,row,col; max=a[0][0]; row=col=0; for(i=0;i<3;i++) for(j=0;j<4;j++) if(*(p+i*4+j)>max) max=*(p+i*4+j); row=i; col=j; } printf("a[%d][%d]=%d\n",row,col,max);

25 8.3.2 二维数组和指针 行数组指针 行数组指针的定义方法如下: 数据类型 (*指针变量名)[二维数组列数];
例如,对上述a数组,行数组指针定义如下: int (*p)[4];

26 8.3.3 指针和字符串 使字符型指针指向字符串的方法 ⑴ 通过定义指针变量时初始化指向字符串。 char *p="a string";
⑵ 利用赋值语句使指针变量指向字符串。 char ch[20],*s; char *str1=ch,*str2; s="string"; str2=str1;

27 8.3.3 指针和字符串 例8-7 用指针复制字符串。 main() { char a[]="I am a student.";
char b[30],*p1,*p2; int i; for(p1=a,p2=b;*p1!='\0';p1++,p2++) *p2=*p1; *p2='\0'; printf("string a is: %s\n",a); printf("string b is: "); for(i=0;b[i]!='\0';i++) printf("%c",b[i]); printf("\n"); }

28 8.3.4 指针数组 指针数组 数组元素为指针类型的数组。指针数组中的每一个元素都是指针变量,它们指向相同类型的数据。 一维指针数组的定义
数据类型 *数组名[数组长度]; 例如: char *days[7]; char *days[7]={"Sunday","Monday","Tuesday", "Wednesday","Thursday","Friday","Saturday"};

29 8.3.4 指针数组 例8-9 分行输出days数组指向的7个字符串。 #include "stdio.h" main() { int i;
char *days[7]={"Sunday","Monday","Tuesday", "Wednesday","Thursday","Friday","Saturday"}; for(i=0;i<7;i++) puts(days[i]); }

30 8.4指针作为函数的参数 8.4.1 简单指针变量作函数参数 8.4.2 指向数组的指针作函数的参数 8.4.3 字符串指针作函数的参数
8.4.4 指针数组作函数的参数 8.4.5 使用带参数的main()函数

31 8.4.1 简单指针变量作函数参数 例8-10用swap()函数交换两个变量的值。 void swap(int *p1,int *p2) {
int temp; temp=*p1; *p1=*p2; *p2=temp; } main() { int x,y; scanf("%d,%d",&x,&y); if(x<y)swap(&x,&y); printf("%d,%d\n",x,y); }

32 8.4.2指向数组的指针作函数的参数 例8-11 求一维数组的最大元素值。 用三个函数实现程序:
用输入函数input()建立数组;用max_a()函数求最大值;用main()函数作为主调函数。 为了方便对函数编写,先假定数组长度为n,指针p指向该数组。那么,input()函数的功能是为p指向的数组输入n个数据;max_a()函数的功能是在具有n个元素、由p指向的数组中找出最大值。 程序

33 8.4.2 指向数组的指针作函数的参数 例8-12 利用一维数组的排序函数对数组排序。 例8-12程序
例8-13有一个3×5的二维数组,对每行前4列元素求和,结果放在最后一列上。 例8-13程序

34 8.4.3字符串指针作函数的参数 例8-14 用字符串指针作函数参数,将输入的一个字符串复制到另一个字符串中。。 例8-14程序
例8-15 用字符串指针作函数参数,改写单词统计程序 。 例8-15程序

35 8.4.4指针数组作函数的参数 例8-16程序 例8-16将一组字符串按字典顺序排序后输出。 分析:
(1)使用指针数组,把各个字符串的开始地址存储起来,通过指针数组就能方便地间接访问各个字符串。 (2)使用字符串比较函数strcmp(),比较两个字符串的大小。 例8-16程序

36 8.4.4指针数组作函数的参数 初始 char *days[7]={"Sunday","Monday","Tuesday", "Wednesday","Thursday","Friday","Saturday"}; 排序后

37 8.4.5 使用带参数的main()函数 带参数的main函数的一般形式 main (int argc, char *argv[ ])
其中:argc表示命令行参数个数,argv是指向命令行参数的指针数组。 在操作系统下运行C程序时,可以以命令行参数形式向main()函数传递参数。 命令行参数的一般形式 运行文件名 参数1 参数2 …… 参数n 指针argv[0]指向的字符串是运行文件名,argv[1]指向的字符串是命令行参数1,argv[2]指向的字符串是命令行参数2,……

38 8.4.5 使用带参数的main()函数 例8-17下列文件的运行文件的文件名为TEST1,按数组方式引用命令行的参数。
#include "stdio.h" main(int argc,char *argv[]) { int i; printf("argc=%d\n",argc); for(i=1;i<argc;i++)   printf("%s\n",argv[i]); } 运行程序,输入的命令行参数为: TEST1 IBM-PC COMPUTER 则执行程序后,输出结果为: argc=3 IBM-PC COMPUTER

39 8.5指针函数和指向函数的指针变量 8.5.1 指针函数 8.5.2 指向函数的指针变量

40 8.5.1 指针函数 函数返回值是指针类型的函数称为指针函数。 指针函数的定义与其他函数有一定区别,需要在函数名前使用“*”符。 一般格式:
数据类型 *函数名(形参表) { 函数体

41 8.5.1 指针函数 程序8-18 程序8-19 例8-18将一组字符串中长度最大的找出来,并输出这个字符串。 分析
设有n组字符串,由指针数组p_string指向,首先编写求最大长度字符串函数max_lenth(),该函数返回最长字符串的首地址,在主函数中调用它,并输出所求字符串。 程序8-18 例8-19 从若干个字符串中,将包含“2000”的第一个字符串找出来,并输出。 程序8-19

42 8.5.2指向函数的指针变量 概念 在定义一个函数之后,编译系统为每个函数确定一个入口地址,当调用该函数的时候,系统会从这个“入口地址”开始执行该函数。存放函数的入口地址的变量就是一个指向函数的指针变量,简称函数的指针。 函数的指针的定义方式 数据类型 (*指针变量名)() 特别值得注意 由于C语言中()的优先级比*高,因此,“*指针变量名”外部必须用括号,否则指针变量名首先与后面的()结合,就是前面介绍的指针函数。如:“int (*pf)();”语句的功能是定义一个指向函数的指针,该函数的返回值为整型数据;“int *f();”语句的功能是定义一个指针的函数,该指针指向一个整型数据。

43 8.5.2指向函数的指针变量 例8-20用指针调用函数,实现从两个数中输出较大者。 #include "stdio.h" main( ) {
int max ( int ,int ); int (*pf)( ); int a,b,c; pf = max; scanf("%d,%d", &a, &b); c= (*pf)(a,b); printf("a=%d,b=%d,max=%d", a, b, c); } int max( int x, int y ) return( x>y ? x : y);

44 8.6动态内存管理 8.6.1 动态内存分配 8.6.2 动态内存管理函数

45 8.6.1 动态内存分配 概念 计算机按需分配内存,在运行时需要多大的空间就分配多大的空间,即动态分配内存。 原因
在编写程序时,因为无法确定要处理数据的规模,如字符串的长度、数值数据的个数等,为保证在数据规模足够大时也能进行处理,在定义变量时就为它说明一个特别大的空间,而在实际运行时,可能只需要这空间的很小一部分,也有可能给出的空间还不够大。这对内存资源利用和程序设计都是不利的。 实现 使用动态内存管理函数。

46 8.6.2动态内存管理函数 1.malloc()函数 函数原型 void *malloc(unsigned int size); 功能
分配一块长度为size字节的连续空间,并将该空间的首地址作为函数的返回值。如果函数没有成功执行,返回值为空指针(NULL或0)。由于返回的指针的基类型为void,应该通过显式类型转换后才能存入其他基类型的指针变量中,否则会有警告提示。 例如 int *p; p=(int *)malloc(sizeof(int)); sizeof运算符返回某类型所需的内存字节数或某变量所分配的字节数,该处返回一个整型变量所需要的字节数2,它即为动态分配内存空间的大小。返回的指针先要通过(int *)转换成整型指针,然后才赋值给整型指针变量P。

47 8.6.2动态内存管理函数 2.free()函数 函数原型 void free(void *block); 功能
释放以前分配给指针变量block的动态空间,但指针变量block不会自动变成空指针。

48 8.6.2动态内存管理函数 3. calloc()函数 函数原型
void *calloc(unsigned n,unsigned size); 功能 以size为单位大小共分配n*size个字节的连续空间,并将该空间的首地址作为函数的返回值。如果函数没有成功执行,返回值为空指针(NULL或0)。该函数比malloc函数方便之处在于,当动态分配数组空间时,malloc函数必须手工计算出数组的总字节数,而calloc函数不用计算。 例如: int *p; p=(int *)calloc(10,sizeof(int));

49 8.6.2动态内存管理函数 程序8-21 例8-21 通过键盘输入一组字符串,然后将包含特定子串的字符串删除,并将其余的字符串输出。 分析
creat()用于建立一组字符串,delete()函数负责将包含特定子串的字符串删除,output()函数用于输出一组字符串。 在creat()函数中,使用动态内存分配函数calloc(),它根据从键盘输入字符串的大小,分配一段内存,把字符串存储起来。 在delete()函数中使用free()函数,把要删除字符串使用的内存释放,从而达到删除字符串的目的。 程序8-21

50 本章小结 1.指针就变量的地址,用来保存指针的变量称为指针变量,通过指针变量就可以实现对其他变量的访问。指针变量可以指向任何一种数据类型。
2.使用如下形式定义指针变量: 数据类型 *指针变量名; 3.当用指针指向数组时,访问数组元素的方法变得灵活多样,既可以使用下标法,也可以使用指针法。 4.使用字符指针处理字符串是C语言中常用的一种方法。 它首先通过一定的方式,用字符指针指向字符串, 然后通过字符指针来访问字符串存贮区域,从而实现对字符串的操作。 5.数组元素为指针类型的数组称为指针数组,指针数组中的每一个元素都是指针变量,它们指向相同类型的数据。

51 本章小结(续) 6.指针作为函数的参数时,在函数间传递的是变量的地址。简单指针变量作函数参数,是指针作函数参数中最基本的内容,它的作用是实现一个简单变量的地址在函数中的传递。 7.指针数组的元素是指针变量,用指针数组可以方便地实现对一组字符串的处理。用指针数组作函数参数,可以实现多字符串处理。 8.字符串指针作函数的参数与数组指针作函数参数没有本质的区别,函数间传递的都是地址值,所不同的仅是指针指向对象的类型不同而已。 9.函数返回值是指针类型的函数称为指针函数,使用指针函数可以获得更多的处理结果。 10.动态内存管理的目的是为了实现动态存储,C语言使用动态内存管理函数来实现动态内存管理。


Download ppt "C语言程序设计 第8章 指针."

Similar presentations


Ads by Google