第七章 指针 计算机公共教学部.

Slides:



Advertisements
Similar presentations
第九章 指针 西安工程大学.
Advertisements

第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数.
第十章 指针 分析C程序的变量所存放的数据:  数值型数据:整数、实数  字符型数据:字符、字符串 这些变量具有以下性质:
第7章 指针 存储地址的变量的类型就是指针类型 能直接对内存地址操作, 实现动态存储管理 容易产生副作用, 初学者常会出错
第七章 指针 教 材: C程序设计导论 主 讲: 谭 成 予 武汉大学计算机学院.
二级指针与二维数组.
C语言程序设计基础 第10章 指针进阶 刘新国.
10.1 二级指针 10.2 指针与二维数组 10.3 指针的动态存储分配 10.4 函数指针 10.5 main函数的参数
第8章 指针 21世纪高等学校精品规划教材.
第 6 章 第 6 章 指 针 指 针 1.
第8章 指针 ● 8.1 指针简介 ● 8.2 指针变量的操作 ● 8.3 数组与指针 ● 8.4 二维数组与指针 ●本章小结 ●本章练习.
C语言基础——指针的高级应用 Week 05.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
6.4 字符串与指针 1. 用字符数组存放一个字符串.
第六节 二维数组和指针 二维数组的地址 对于一维数组: (1)数组名array表示数组的首地址, 即array[0]的地址;
8.1 指针的概念 8.2 指针变量 8.3 指针变量的基础类型 8.4 指针的运算 8.5 指针与一维数组 8.6 指针应用实例
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
程序设计基础.
第6章 指针 学习目的与要求: 了解指针的概念和相关术语 熟练掌握指向变量、数组和字符串的指针变量的使用方法 了解指向函数的指针变量
指 针 为什么要使用指针 指针变量 指针与数组 返回指针值的函数 动态内存分配 通过指针引用字符串 指向函数的指针 小 结 习 题.
目录 10.1 指针的基本概念 10.2 指向变量的指针变量 10.3 指向数组的指针变量 10.4 指向函数的指针变量和指针型函数
第八章 指 针 8.1 指针的概念与定义 8.2 指针作函数参数 8.3 指针与数组 8.4 指针与函数 8.5 复杂指针.
第 十 章 指 针.
项目六 用指针优化学生成绩排名 项目要求 项目分析
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
第五章 指针 5.1 指针的概念和定义 5.2 指针运算 5.3 指针和数组 5.4 字符串指针 5.5 指针数组 5.6 指向指针的指针
二维数组的指针表示 与复杂的指针例子 专题研讨课之三.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第8章 指针.
第六章 指针 指针的概念 指针的运算 指向变量的指针 指向数组的指针 指向函数的指针 二级指针 主讲:李祥 时间:2015年10月.
第八章 使用指针.
第十章 指针.
欲穷千里,更上层楼 第十章 指 针 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,
第五章 习题课 电子信息与计算机科学系 曾庆尚.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C++大学基础教程 第6章 指针和引用 北京科技大学 信息基础科学系.
第五章 指针 5.1 指针的概念 5.2 指针与数组 5.3 字符串指针.
9.1 地址、指针和变量 9.2 指针运算 9.3 指针与数组 9.4 函数与指针 9.5 程序综合举例 9.6 上机实训.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C语言复习3----指针.
第一章 程序设计和C语言 主讲人:高晓娟 计算机学院.
C语言程序示例: 1.输入10个数,按从小到大的顺序排序。 2.汉诺塔问题。.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
C语言大学实用教程 第7章 指针 西南财经大学经济信息工程学院 刘家芬
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
第八章 指標 (Pointer).
指针 几个概念:  指针也是一种数据类型,具有指针类型的变量,称为指针变量。
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第6讲 指针与引用 6.1 指针 6.2 引用.
C语言程序设计 第一章 数据类型, 运算符与表达式 第二章 顺序程序设计 第三章 选择结构程序设计 第四章 循环控制 第五章 数组.
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。
第4章 Excel电子表格制作软件 4.4 函数(一).
第九节 赋值运算符和赋值表达式.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C程序设计.
C语言程序设计 第8章 指针.
基本知识 数据类型、变量、常量、运算符.
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第八章 指 针 北京邮电大学出版社.
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
第7章 地址和指针 7.1 地址和指针的概念 7.2 指针变量的定义和指针变量的基类型 7.3 给指针变量赋值 7.4 对指针变量的操作
Presentation transcript:

第七章 指针 计算机公共教学部

教学目的与要求 掌握指针的概念,指针变量的定义与引用;认识指针的作用和意义;弄清指针与数组的关系;理解使用指针指向数组在程序设计所带来的方便;了解指向函数的指针、返回指针值的函数、多级指针。

教学重点与难点 指针与地址的基本概念,指针与变量的关系,指针与数组,指针与字符串,指针的应用。

7.1 地址和指针的概念 什么是指针 i k 变量与地址 程序中: int i; float k; 变量是对程序中数据 存储空间的抽象 7.1 地址和指针的概念 什么是指针 变量与地址 内存中每个字节有一个编号-----地址 …... 2000 2001 2002 2005 内存 2003 程序中: int i; float k; i 编译或函数调用时为其分配内存单元 k 变量是对程序中数据 存储空间的抽象

指针与指针变量 指针:一个变量的地址 指针变量:专门存放变量地址的变量叫指针变量 10 变量的内容 变量的地址 指针变量 变量地址(指针) …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 指针 变量的地址 变量的内容 2000 指针变量 指针变量 变量 变量地址(指针) 变量值 指向 地址存入

&与*运算符 含义 10 i_pointer = &i = &(*i_pointer) i_pointer &i &(*i_pointer) 含义: 取变量的地址 单目运算符 优先级: 2 结合性:自右向左 含义: 取指针所指向变量的内容 单目运算符 优先级: 2 结合性:自右向左 两者关系:互为逆运算 理解 2000 10 i_pointer *i_pointer i …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 指针变量 i_pointer = &i = &(*i_pointer) i = *i_pointer = *(&i) i_pointer &i &(*i_pointer) i *i_pointer *(&i) i_pointer-----指针变量,它的内容是地址量 *i_pointer----指针的目标变量,它的内容是数据 &i_pointer---指针变量占用内存的地址

间接访问:通过存放变量地址的变量去访问变量 直接访问与间接访问 直接访问:按变量地址存取变量值 间接访问:通过存放变量地址的变量去访问变量 指针变量 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 例 i=3; -----直接访问 20 3 例 *i_pointer=20; -----间接访问

10 例 k=i; k=*i_pointer; 例 k=i; --直接访问 k=*i_pointer; --间接访问 10 …... 指针变量 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 整型变量k 10

7.2指针变量的类型说明 指针变量的定义 存储类型 类型 *指针变量; int *p1;/* 定义一个名为p1的整型类型的指针变量 */ Static int *p2; /* 定义一个名为p2的字符类型的指针变量 */

表示定义指针变量 不是‘*’运算符 合法标识符 指针的目标变量的数据类型 指针变量与其所指向的变量之间的关系 3 变量i 2000 i_pointer *i_pointer i &i i=3; *i_pointer=3 3 变量i 2000 i_pointer *i_pointer i &i i=3; *i_pointer=3 指针变量的定义 一般形式:[存储类型] 数据类型 *指针名; 例 int *p1,*p2; float *q ; static char *name; 表示定义指针变量 不是‘*’运算符 指针变量本身的存储类型 合法标识符 指针的目标变量的数据类型 注意: 1、int *p1, *p2; 与 int p1, p2; 2、指针变量名是p1,p2 ,不是*p1,*p2 3、指针变量只能指向定义时所规定类型的变量 4、指针变量定义后,变量值不确定,应用前必须先赋值

指针变量的初始化 一般形式:[存储类型] 数据类型 *指针名=初始地址值; 例 int i; int *p=&i; 赋给指针变量, 不是赋给目标变量 变量必须已说明过 类型应一致 例 int i; int *p=&i; int *q=p; 例 int *p=&i; int i; 用已初始化指针变量作初值 例 main( ) { int i; static int *p=&i; .............. } () 不能用auto变量的地址 去初始化static型指针

p指向地址为0的单元, 系统保证该单元不作它用 表示指针变量值没有意义 零指针与空类型指针 零指针: 定义:指针变量值为零 表示: int * p=0; p指向地址为0的单元, 系统保证该单元不作它用 表示指针变量值没有意义 #define NULL 0 int *p=NULL: 例 int *p; ...... while(p!=NULL) { ...… } 例 char *p1; void *p2; p1=(char *)p2; p2=(void *)p1; p=NULL与未对p赋值不同 用途: 避免指针变量的非法引用 在程序中常作为状态比较 表示不指定p是指向哪一种 类型数据的指针变量 void *类型指针 表示: void *p; 使用时要进行强制类型转换

7.3 指针变量的引用 5,10 #include “stdio.h“ main() { int a=5,b,c,*p; p=&a; 7.3 指针变量的引用 #include “stdio.h“ main() { int a=5,b,c,*p; p=&a; b=*p; c=a+*p; printf(“%d,%d”,b,c); } 5,10

指针变量常见使用方法 (1)给指针变量赋值 一般形式:指针变量=表达式; int i,*p; p=&i; (2)直接引用指针变量名 int i,j,*p=&i,*q; q=p; (3)通过一般指针变量来引用它所指向的变量 一般形式:*指针变量名 int i=1,j=2,k,*p=&i; k=*p+j;

7.4 指针作为函数参数 指针作为函数参数是地址传递,可以改变实参的值。 void swap(int *x,int *y) { int t;t=*x;*x=*y;*y=t; } main() int a=3,b=5; swap(&a,&b); printf("a=%d,b=%d\n“,a,b);

7.5 数组与指针 p array[0] 指向数组元素的指针变量 array[1] 例 int array[10]; int *p; ... 整型指针p &array[0] p 指向数组元素的指针变量 例 int array[10]; int *p; p=&array[0]; // p=array; 或 int *p=&array[0]; 或 int *p=array; 数组名是表示数组首地址的地址常量

如 int i, *p; p=1000; () i=p; () 指针的运算 指针变量的赋值运算 p=&a; (将变量a地址p) p=array; (将数组array首地址p) p=&array[i]; (将数组元素地址p) p1=p2; (指针变量p2值p1) 不能把一个整数p,也不能把p的值整型变量 指针变量与其指向的变量具有相同数据类型

pi  p id (i为整型数,d为p指向的变量所占字节数) p++, p- -, p+i, p-i, p+=i, p-=i等 指针的算术运算: pi  p id (i为整型数,d为p指向的变量所占字节数) p++, p- -, p+i, p-i, p+=i, p-=i等 若p1与p2指向同一数组,p1-p2=两指针间元素个数(p1-p2)/d p1+p2 无意义 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a数组 p p+1,a+1 p+i,a+i p+9,a+9 例 p指向float数,则 p+1  p+1 4 例 p指向int型数组,且p=&a[0]; 则p+1 指向a[1] 1 例 int a[10]; int *p=&a[2]; p++; *p=1; 例 int a[10]; int *p1=&a[2]; int *p2=&a[5]; 则:p2-p1=3;

指针变量的关系运算 若p1和p2指向同一数组,则 p1<p2 表示p1指的元素在前 p1>p2 表示p1指的元素在后 p1==p2 表示p1与p2指向同一元素 若p1与p2不指向同一数组,比较无意义

a[i]  p[i]  *(p+i) *(a+i) a[i]  *(a+i) 通过指针引用数组元素 a[0] a[1] a[2] a[3] a[9] ... a a+9 a+1 a+2 地址 元素 下标法 a[0] a[1] a[2] a[3] a[9] ... p p+9 p+1 p+2 地址 元素 指针法 *p *(p+1) *(p+2) *(p+9) *a *(a+1) *(a+2) *(a+9) p[0] p[1] p[2] p[9] a[i]  p[i]  *(p+i) *(a+i)

例 数组元素的引用方法 p142 例7.4 main() { int a[5],i,*pa,*qa; pa=qa=a; for(i=0;i<5;i++){ *qa=i+1; qa++; } for(i=0;pa<qa;i++){ printf("a[%d]=%d ",i,*pa); pa++; a[0] a[1] a[2] a[3] a[4] pa 1 2 3 4 5

7.6 数组名和数组指针变量作为函数参数 一级指针变量与一维数组的关系 int *p 与 int q[10] 数组名q是指针(地址)常量 p=q; p+i 是q[i]的地址 数组元素的表示方法:下标法和指针法, 即若p=q, 则p[i]  q[i]  *(p+i)  *(q+i) 形参数组实质上是指针变量,即int q[ ]  int *q 在定义指针变量(不是形参)时,不能把int *p 写成int p[]; 系统只给p分配能保存一个指针值的内存区(一般2字节);而给q分配2*n字节的内存区

printf("\ninput 5 score:\n"); for(i=0;i<5;i++) scanf("%f",&sco[i]); 7.6用数组名作函数参数 例7.5 用数组名和数组指针变量作函数参数,求输入一个学生5门成绩至数组a,求平均成绩。 (p142) #include "stdio.h" float aver(float *pa) { int i; float s=0; for(i=0;i<5;i++) s=s+*pa++; s/=5; return s; } main() { float sco[5],av,*sp; int i; sp=sco; printf("\ninput 5 score:\n"); for(i=0;i<5;i++) scanf("%f",&sco[i]); av=aver(sp); printf("average score is %5.2f\n",av); }

7.7 指向多维数组的指针变量 int a[3][4];

int a[3][4]; a a+1 a+2 行指针与列指针 *(a[0]+1) *(*(a+0)+1) 2000 2000 a[0] 2008 2016 a a+1 a+2 2000 2002 2008 2010 2016 2018 a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] a[0]+1 a[1]+1 a[2]+1 *(a+0)+1 *(a+1)+1 *(a+2)+1 对于二维数组: (1)a是数组名, 包含三个元素 a[0],a[1],a[2] (2)每个元素a[i] 又是一个一维数组, 包含4个元素 基类型

int a[3][4]; a a+1 a+i=&a[i]=a[i]=*(a+i) =&a[i][0], 值相等,含义不同 2000 2008 2016 2002 2010 2018 a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] a a+1 a+2 对二维数组 int a[3][4],有 a-----二维数组的首地址,即第0行的首地址 a+i-----第i行的首地址 a[i]  *(a+i)------第i行第0列的元素地址 a[i]+j  *(a+i)+j -----第i行第j列的元素地址 *(a[i]+j)  *(*(a+i)+j)  a[i][j] a+i=&a[i]=a[i]=*(a+i) =&a[i][0], 值相等,含义不同 a+i  &a[i],表示第i行首地址,指向行 a[i]  *(a+i)  &a[i][0],表示第i行第0列元素地址,指向列

int a[3][4]; 地址表示: (1) a+1 (2) &a[1][0] (3) a[1] (4) *(a+1) 行指针 列指针 地址表示: (1) &a[1][2] (2) a[1]+2 (3) *(a+1)+2 (4)&a[0][0]+1*4+2 二维数组元素表示形式: (1)a[1][2] (2)*(a[1]+2) (3)*(*(a+1)+2) (4)*(&a[0][0]+1*4+2)

*(a[1]+2),*(*(a+1)+2),a[1][2] 表示形式 含义 地址 a 二维数组名,数组首地址 a[0],*(a+0),*a 第0行第0列元素地址 a+1 第1行首地址 a[1],*(a+1) 第1行第0列元素地址 a[1]+2,*(a+1)+2,&a[1][2] 第1行第2列元素地址 *(a[1]+2),*(*(a+1)+2),a[1][2] 第1行第2列元素值 2000 2008 2012 13

一维数组指针变量维数和 二维数组列数必须相同 指向一维数组的指针变量 定义形式: 数据类型 (*指针名)[一维数组维数]; 例 int (*p)[4]; int a[3][4]; a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] a a+1 a+2 p p+1 p+2 p[0]+1或 *p+1 p[1]+2或 *(p+1)+2 p的值是一维数组的 首地址,p是行指针 ( )不能少 int (*p)[4]与int *p[4]不同 可让p指向二维数组某一行 如 int a[3][4], (*p)[4]=a; *(*p+1)或 (*p)[1] *(*(p+1)+2) 一维数组指针变量维数和 二维数组列数必须相同

p p p 例 一维数组指针变量举例 main() 例 一维数组指针变量举例 int a[3][4]; a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] p main() { static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int i,j,(*p)[4]; for(p=a,i=0;i<3;i++,p++) for(j=0;j<4;j++) printf("%d ",*(*p+j)); printf("\n"); } p  p[0][j] p p=a[0]; p=*a; p=&a[0][0]; p=&a[0]; p=a[0]; p=*a; p=&a[0][0]; p=&a[0];

二维数组与一维数组指针变量的关系 如 int a[5][10] 与 int (*p)[10]; 二维数组名a是一个指向有10个元素的一维数组的指针常量 p=a+i 使 p指向二维数组的第i行 *(*(p+i)+j)  a[i][j] 系统只给p分配能保存一个指针值的内存区(一般2字节);而给a分配2*5*10字节的内存区

7.8 字符串与指针 字符串表示形式 用字符数组实现 例 main( ) { char string[]=“I love China!”; \0 例 main( ) { char string[]=“I love China!”; printf(“%s\n”,string); printf(“%s\n”,string+7); }

{ char *string=“I love China!”; printf(“%s\n”,string); string+=7; 用字符指针实现 I l o v e C h i string n ! a \0 字符指针初始化:把字符串首地址赋给string  char *string; string=“I love China!”; 例 main( ) { char *string=“I love China!”; printf(“%s\n”,string); string+=7; while(*string) { putchar(string[0]); string++; } string *string!=‘\0’

字符串指针作函数参数 例 用函数调用实现字符串复制 (1)用字符数组名作参数 (2)用指向字符指针变量作参数 b y u a r s t n d e to o . \0 a I m t e c h \0 r . from I a e c h \0 r . t m 例 用函数调用实现字符串复制 (1)用字符数组名作参数 (2)用指向字符指针变量作参数

void copy_string(char from[],char to[]) { int i=0; 字符串指针作函数参数 a I m t e c h \0 r . from b y u a r s t n d e to o . \0 I a e c h \0 r . t m void copy_string(char from[],char to[]) { int i=0; while(from[i]!='\0') { to[i]=from[i]; i++; } to[i]='\0'; main() { char a[]="I am a teacher."; char b[]="You are a student."; printf("string_a=%s\n string_b=%s\n",a,b); copy_string(a,b); printf("\nstring_a=%s\nstring_b=%s\n",a,b); 例 用函数调用实现字符串复制 void copy_string(char *from,char *to) { for(;*from!='\0';from++,to++) *to=*from; *to='\0'; } main() { char *a="I am a teacher."; char *b="You are a student."; printf("string_a=%s\nstring_b=%s\n",a,b); copy_string(a,b); printf("\nstring_a=%s\nstring_b=%s\n",a,b); (1)用字符数组名作参数 (2)用字符指针变量作参数

7.9字符指针变量与字符数组 char *cp; 与 char str[20]; str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址 char str[20]; str=“I love China!”; () char *cp; cp=“I love China!”; () str是地址常量;cp是地址变量 cp接受键入字符串时,必须先开辟存储空间 例 char str[10]; scanf(“%s”,str); () 而 char *cp; scanf(“%s”, cp); () 改为: char *cp,str[10]; cp=str; scanf(“%s”,cp); ()

字符串与数组关系 字符串用一维字符数组存放 字符数组具有一维数组的所有特点 数组名是指向数组首地址的地址常量 数组元素的引用方法可用指针法和下标法 数组名作函数参数是地址传递等 区别 存储格式:字符串结束标志 赋值方式与初始化 输入输出方式:%s %c scanf(“%s”,str); printf(“%s”,str); gets(str); puts(str); char str[]={“Hello!”}; () char str[]=“Hello!”; () char str[]={‘H’,‘e’,‘l’,‘l’,‘o’,‘!’}; () char *cp=“Hello”; () int a[]={1,2,3,4,5}; () int *p={1,2,3,4,5}; () char str[10],*cp; int a[10],*p; str=“Hello”; () cp=“Hello!”; () a={1,2,3,4,5}; () p={1,2,3,4,5}; ()

7.10 函数指针变量 函数指针:函数在编译时被分配的入口地址,用函数名表示 ( )不能省 专门存放函数入口地址 max …... 指令1 指令2 指向函数的指针变量 定义形式: 数据类型 (*指针变量名)(); 如 int (*p)(); 函数指针变量赋值:如p=max; ( )不能省 int (*p)() 与 int *p()不同 专门存放函数入口地址 可指向返回值类型相同的不同函数 函数返回值的数据类型 函数调用形式: c=max(a,b);  c=(*p)(a,b); 对函数指针变量pn, p++, p--无意义 函数指针变量指向的函数必须有函数说明

例 用函数指针变量调用函数,比较两个数大小 main() { int maxnum(int ,int), (*p)(); int a,b,c; p=max; scanf("%d,%d",&a,&b); c=(*p)(a,b); printf("a=%d,b=%d,max=%d\n",a,b,c); } int maxnum(int x,int y) { int z; if(x>y) z=x; else z=y; return(z); main() { int max(int ,int); int a,b,c; scanf("%d,%d",&a,&b); c=max(a,b); printf("a=%d,b=%d,max=%d\n",a,b,c); } int max(int x,int y) { int z; if(x>y) z=x; else z=y; return(z);

7.11 指针型函数 main() { float score[][4]={{60,70,80,90}, {56,89,67,88},{34,78,90,66}}; float *search(float (*pointer)[4],int n), *p; int i,m; printf("Enter the number of student:"); scanf("%d",&m); printf("The scores of No.%d are:\n",m); p=search(score,m); for(i=0;i<4;i++) printf("%7.2f\t",*(p+i));} float *search(float (*pointer)[4], int n) { float *pt; pt=*(pointer+n); return(pt); } 7.11 指针型函数 函数定义形式: 类型标识符 *函数名(参数表); 例 int *f(int x, int y) 例 指针函数实现:有若干学生成绩,要求输入学生序号后, 能输出其全部成绩 p p p p pointer pointer+1 34 78 90 66 56 89 67 88 60 70 80 score数组

7.12 指针数组和指向指针的指针 用于处理二维数组或多个字符串 指针数组 定义:数组中的元素为指针变量 7.12 指针数组和指向指针的指针 用于处理二维数组或多个字符串 指针数组 定义:数组中的元素为指针变量 定义形式:[存储类型] 数据类型 *数组名[数组长度说明]; 例 int *p[4]; 指针数组赋值与初始化 指针本身的存储类型 指针所指向变量的数据类型 赋值: main() { int b[2][3],*pb[2]; pb[0]=b[0]; pb[1]=b[1]; …….. } int *pb[2] pb[0] pb[1] int b[2][3] 1 2 3 4 6 区分int *p[4]与int (*p)[4] 初始化: main() { int b[2][3],*pb[ ]={b[0],b[1]}; …….. } int *pb[2] pb[0] pb[1] int b[2][3] 1 2 3 4 6

p[0]=a; p[1]=b; p[2]=c; p[3]=NULL; …….. } 或: { char *p[4]; 指针数组赋值与初始化 L i s p \0 F o r t r a n \0 B a s i c \0 p[0] p[1] p[2] p[3] 赋值: main() { char a[]="Fortran"; char b[]="Lisp"; char c[]="Basic"; char *p[4]; p[0]=a; p[1]=b; p[2]=c; p[3]=NULL; …….. } 或: { char *p[4]; p[0]= "Fortran"; p[1]= "Lisp"; p[2]= "Basic"; p[3]=NULL; 初始化: main() { char *p[]={"Fortran", "Lisp", "Basic",NULL}; …….. } L i s p \0 F o r t r a n \0 B a s i c \0 p[0] p[1] p[2] p[3]

二维数组与指针数组区别: 指针数组元素的作用相当于二维数组的行名 但指针数组中元素是指针变量 二维数组存储空间固定 二维数组的行名是地址常量 char name[5][9]={“gain”,“much”,“stronger”, “point”,“bye”}; g a i n \0 s t r o n g e r \0 p o i n t \0 m u c h \0 b y e \0 g a i n \0 s t r o n g e r \0 p o i n t \0 m u c h \0 name[0] name[1] name[2] name[3] name[4] b y e \0 char *name[5]={“gain”,“much”,“stronger”, “point”,“bye”}; 指针数组元素的作用相当于二维数组的行名 但指针数组中元素是指针变量 二维数组的行名是地址常量 二维数组存储空间固定 字符指针数组相当于可变列长的二维数组

一级指针 单级间接寻址 二级指针 一级指针 目标变量 二级间接寻址 多级指针 定义: 指向指针的指针 一级指针:指针变量中存放目标变量的地址 例 int *p; int i=3; p=&i; *p=5; &i 3 P(指针变量) i(整型变量) 一级指针 单级间接寻址 二级指针:指针变量中存放一级指针变量的地址 例 int **p1; int *p2; int i=3; p2=&i; p1=&p2; **p1=5; p1 &p2 &i 3 P2(指针变量) i(整型变量) 二级指针 一级指针 目标变量 二级间接寻址

定义形式:[存储类型] 数据类型 **指针名; 如 char **p; *p是p间接指向对象的地址 **p是p间接指向对象的值 最终目标变量的数据类型 指针本身的存储类型 i p1 p2 3 &i &p1 例 int i=3; int *p1; int **p2; p1=&i; p2=&p1; **p=5; **p2, *p1 *p2 例 int i, **p; p=&i; ()//p是二级指针,不能用变量地址为其赋值 多级指针 例 三级指针 int ***p; 四级指针 char ****p;

#include <stdio.h> void swap(int *r,int *s) { int *t; t=r; r=s; b p q 例 一级指针与二级指针 #include <stdio.h> void swap(int *r,int *s) { int *t; t=r; r=s; s=t; } main() { int a=1,b=2,*p,*q; p=&a; q=&b; swap(p,q); printf("%d,%d\n",*p,*q); a b p q r s a b p q s r a b p q 输出: 1,2

#include <stdio.h> void swap(int **r,int **s) { int *t; t=*r; 例 一级指针与二级指针 a b p q #include <stdio.h> void swap(int **r,int **s) { int *t; t=*r; *r=*s; *s=t; } main() { int a=1,b=2,*p,*q; p=&a; q=&b; swap(&p,&q); printf("%d,%d\n",*p,*q); a b r s p q a b r s p q b a p q 输出: 2,1

char *name[]={"hello","good","world","bye",""}; p=name+1; 例 用二级指针处理字符串 用*p可输出地址(%o或%x), 也可用它输出字符串(%s) #define NULL 0 void main() { char **p; char *name[]={"hello","good","world","bye",""}; p=name+1; printf("%o : %s ", *p,*p); p+=2; while(**p!=NULL) printf("%s\n",*p++); } name[0] name[1] name[2] name[3] name[4] char *name[5] world bye \0 hello good name p *(p++) p 运行结果: 644 : good bye

二级指针与指针数组的关系 int **p 与 int *q[10] 指针数组名是二级指针常量 p=q; p+i 是q[i]的地址 指针数组作形参,int *q[ ]与int **p完全等价;但作为变量定义两者不同 系统只给p分配能保存一个指针值的内存区;而给q分配10块内存区,每块可保存一个指针值

指针的数据类型 定义 含义 int i; 定义整型变量i p为指向整型数据的指针变量 int *p; int a[n]; 定义含n个元素的整型数组a int *p[n]; n个指向整型数据的指针变量组成的指针数组p int (*p)[n]; p为指向含n个元素的一维整型数组的指针变量 int f(); f为返回整型数的函数 int *p(); p为返回指针的函数,该指针指向一个整型数据 int (*p)(); p为指向函数的指针变量,该函数返回整型数 int **p; p为指针变量,它指向一个指向整型数据的指针变量

例 下列定义的含义 (1)int *p[3]; (2)int (*p)[3]; (3)int *p(int); (4)int (*p)(int); (5)int *(*p)(int); 指针数组 指向一维数组的指针 返回指针的函数 指向函数的指针,函数返回int型变量 指向函数的指针,函数返回int 型指针

7.13 有关指针的数据类型和指针运算的小结 有关指针数据类型的小结 定义 含义 int i ; int *p; int a[n]; 定义整型变量 int *p; p为指向整型数据的指针变量 int a[n]; 定义整型数组a,它有n个元素 int *p[n]; 定义整型数组p,它由n个指向整型数据的指针元素组成 int (*p)[n]; p为指向含n个元素的一维数组的指针变量 int f(); f为返回整型函数值的函数 int *p(); p为返回一个指针的函数,该指针指向整型数据 int (*p)() p为指向函数的指针,该函数返回一个整数值 int **p p是一个指针变量,它指向一个指向整数数据的指针变量

指针运算小结 指针变量加(减)一个整数 例如:p++、p--、p+i、p-i、p+=i、p-=i等。 p=&a(将变量a的地址赋给p) p=array; (将数组array首地址赋给p) p=&array[i];(将数组array第i个元素的地址赋给p) p=max; (max为已定义的函数,将max的入口地址赋给p) p1=p2; (p1和p2都是指针变量,将p2的值赋给p1) (2) 指针变量赋值

(3) 指针变量可以有空值,即该指针变量不指向任何变量 p=NULL; 假如p1指向a[1],p2指向a[4],则p2-p1=4-1=3。 但p1+p2并无实际意义。 (4) 两个指针变量可以相减 (5) 两个指针变量比较 p1<p2,

思考:如p是指向二维数组中a中元素的指针,开始指向a[0][0],则a[i][j]的地址如何表示?如p是指向二维数组中每一行的指针,则又有什么不同?