第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。

Slides:



Advertisements
Similar presentations
《C语言程序设计》复习
Advertisements

第九章 指针 西安工程大学.
电子成绩单项目实现.
C语言程序设计教程 单位:德州学院计算机系.
第一章 C语言概述 计算机公共教学部.
第8章 指针 ● 8.1 指针简介 ● 8.2 指针变量的操作 ● 8.3 数组与指针 ● 8.4 二维数组与指针 ●本章小结 ●本章练习.
C语言基础——指针的高级应用 Week 05.
专题研讨课二: 数组在解决复杂问题中的作用
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
105學年度高一普通科(1~8班) 新生選修課程說明
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
复习与总结.
程序设计基础.
第六章 数 组 主讲教师 贾月乐 联系电话:
C语言程序设计 课程 第5章 数组 主讲:李祥 博士、副教授 单位:软件学院软件工程系.
由C程序结构所知,一个完整的C语言程序是由一个且只能有一个main()函数(又称主函数)和若干个其他函数组合而成的。而前面各章仅学习main()函数的编程,本章将介绍其他函数的编程,包括其他函数的定义、调用、参数传递及变量的作用域等。
選擇排序法 通訊一甲 B 楊穎穆.
Introduction to the C Programming Language
目录 10.1 指针的基本概念 10.2 指向变量的指针变量 10.3 指向数组的指针变量 10.4 指向函数的指针变量和指针型函数
项目六 用指针优化学生成绩排名 项目要求 项目分析
结构体和共用体 2 梁春燕 华电信息管理教研室.
C 程式設計— 指標 台大資訊工程學系 資訊系統訓練班.
目录 第八章 数组 1 简单学生成绩管理系统的开发 2 一维数组 3 多维数组 4 字符数组 5 数组作函数参数.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
Introduction to the C Programming Language
C语言程序设计 李祥.
第八章 函数.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
第五章 指针 5.1 指针的概念和定义 5.2 指针运算 5.3 指针和数组 5.4 字符串指针 5.5 指针数组 5.6 指向指针的指针
第6章 函数 学习的意义.
6.4.1指针与二维数组 1、二维数组结构的分析 设有数组定义为:int a[3][4]; 则有: a表示数组在内存中的首地址。
第二章 C++对C 在非面向对象方面的改进 更简洁,更安全.
第8章 指针.
第八章 使用指针.
谭浩强 编著 中国高等院校计算机基础教育课程体系规划教材 C++程序设计.
第十章 指针.
数组 梁春燕 华电信息管理教研室.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
六、函数 教学目标: 函数的概念、定义、调用和返回 带自定义函数的程序设计 递推算法 递归思想及算法实现 函数的参数传递方式 C语言程序设计.
第8章 函数 函数参数和函数的值 概述 函数定义的一般形式 函数的调用(嵌套调用、递归调用) 数组作为函数参数
目录 9.1 结构体类型 9.2 共用体类型 9.3 枚举类型 9.4 类型声明符typedef 1.
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
C语言复习3----指针.
第一章 程序设计和C语言 主讲人:高晓娟 计算机学院.
C语言程序示例: 1.输入10个数,按从小到大的顺序排序。 2.汉诺塔问题。.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
第八章 指標 (Pointer).
C语言的特点 1. C程序由许多函数组成 2. C程序必须有且只有一个主函数main( ) 3. 函数用“{”和“}”表示起点和终点
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第十四章 若干深入问题和C独有的特性 作业: 函数指针 函数作参数 函数副作用 运算 语句 位段 存储类别 编译预处理
C程序设计.
第5章 函 数.
第一章 C语言概述 教师:周芸.
第九章 指针.
静定结构位移计算 ——互等定理 主讲教师:戴萍.
第二章 基本数据类型 ——数据的表示.
C程序设计.
第四章 函数 丘志杰 电子科技大学 计算机学院 软件学院.
第五章 逻辑运算和判断选取控制 §5.1 关系运算符和关系表达式
第七章  数 组.
单片机应用技术 (C语言版) 第4章 C51程序设计入门
第三章 高级函数特性.
基本資料型態 變數與常數 運算子 基本的資料處理 授課:ANT 日期:2014/03/03.
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第9章 C++程序设计初步 9.1 C++的特点 9.2 最简单的C++程序 9.3 C++的输入输出 9.4 函数的重载
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
C程序设计 复习 1、计算机系统的组成 外部设备:输入、输出设备(同人打交道《十进制》)
C语言基础学习 从外行到入门.
Presentation transcript:

第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。 第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。 内存单元的地址与内存单元的内容是两个完全不同的概念。 在编译时给出了变量名和地址的对应关系。

以前在程序中定义整形等变量。如 int a,b; 表示a和b申请整形单元,分别存放两个整形值。 我们也可以定义一种特殊的变量,它用来存放内存单元地址。这种变量的值是一个地址,它的作用是:根据地址去找相应的单元,因此,这种装载地址的变量又可称为“指针变量”。 指针变量的值就是指针即地址。

10.2 变量的指针和指向变量的指针变量 变量的指针就是变量的地址。存放地址的变量称谓指针变量。 为了表示指针变量和它所指向的变量之间联系,程序中用*符号表示“指向” 如用i_point表示指针变量,而*i_point就表示i_point指向的变量。 10.2.1 定义一个指针变量 C语言规定所有变量在使用前必须定义,指定其类型,并按此分配内存单元。

int i,j; int *point1,*point2; 定义了两个指向整形变量的指针变量。 定义指针变量要指定“基类型” 基类型是指针变量指向的变量的类型。 指针变量的定义形式: 基类型 *指针变量名 那么如何给指针变量赋值呢? point1=&i; point1=&j;

10.2.2 指针变量的引用 指针变量只能存放地址(指针),有两个有关的运算符: (1)&:取址运算符,&a (2)*:指针运算符(“间接运算符”),*p main() {int a,b;int *point1,*point2; a=100;b=20; point1=&a; point2=&b; printf(“%d,%d\n”,a,b); printf(“%d,%d\n”, *point1,*point2);}

point1=&*point2; ? b=*&a; ? main() { int *p1,*p2,*p,a,b; a=10;b=90; p1= &a;p2=&b; if(a<b){p=p1;p1=p2;p2=p;} printf(“%d,%d\n”,*p1,*p2); }

10.2.3 指针变量作为函数参数 函数参数可以是指针变量 swap(int *p1,int *p2) { int temp; temp=*p1;*p1=*p2;*p2=temp;} main() {int a,b, *point1,*point2; a=10;b=90; point1=&a; point2=&b; if(a<b)swap(point1,point2); printf(“%d,%d\n”, *point1,*point2);}

10.3 数组的指针和指向数组的指针变量 一个变量有地址,一个数组包括若干个元素,每个元素都有地址. 数组的指针是指数组的起始元素的地址. 引用数组元素可用下标法,也可用指针法,即用指针指向所引用的元素.

10.3.1 指向数组元素的指针 int a[10]; int *p; p=&a[8]; C语言规定数组名代表数组的首地址,也就是第0号元素的地址. 下面两个句子等价: p=&a[0]; p=a;

10.3.2 通过指针引用数组元素 按C语言规定:如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素(而不是将的p的值简单加1). 如果p的初值为&a[0],则 (1)p+i和a+i就是a[i]的地址 (2)*(p+i)和*(a+i)是p+i和a+i所指向的数组元素,即a[i]。 可以看出,[ ]实际上是变址运算符 (3)指向数组的指针变量也可以带下标,如 p[i]与*(p+i)等价.

10.3.3 用数组名作函数参数 例: main() inv(int arr[ ],int n) { int array[10]; { : : inv(array,10); } : } 用数组名作参数时,如果形参数组中各元素值发生变化,实参数组值随之变化.

void inv(int arr[ ],int n) { int t,i,j,m=(n-1)/2; for(i=0;i<=m;i++) { j=n-1-i;t=arr[i];arr[i]=arr[j];arr[j]=t;} } main() { int i,a[10]={2,4,54,6,7,3,31,56,23,65}; inv(a,10); for(i=0;i<=9;i++) printf(“%d”,a[i]);

f(int arr[ ],int n)等价于f(int *arr,int n) 例: 函数定义为: 函数调用为: void swap(int x,int y) swap(a[1],a[2]); 请大家注意: (1)“值传递”和“地址传递” (2)两者之间的异同点

int m1,m2; void m_value(int array[ ],int n) { int *p,*array_end; array_end=array+n; m1=m2=*array; for(p=array+1;p<array_end;p++) if(*p>m1)m1=*p; else if(*p<m2)m2=*p;} main() { int i,num[10]; for(i=0;i<10;i++)scanf(“%d”,&num[i]); m_value(num,10); printf(“%d,%d”,m1,m2);}

函数参数为数组时: (1)形参和实参都是数组名,如: main() f(int arr[ ],int n) { int a[10]; { : : f(a,10); } : } (2)实参是数组名,形参是指针变量,如: main() f(int *arr,int n) f(a,10); }

(3)形参和实参都是指针变量,如: main() f(int *arr,int n) { int a[10],*p=a; { : : f(p,10); } : } (4)实参是指针变量,形参是数组名,如: main() f(int arr[ ],int n) f(p,10); }

选择法排序 sort(int x[ ],int n) { int i,j,k,t; for(i=0;i<n-1;i++) {k=i; for(j=i+1;j<n;j++) if(x[j]>x[k])k=j; if(k!=i){t=x[i];x[i]=x[k];x[k]=t;} }

10.3.4 指向多维数组的指针和指针变量 1、多维数组的地址 考查:int a[3][4]; a是一个数组名。 a数组包含3行,即看成3个元素: a[0]、a[1]、a[2]。而一个元素又是一个一维数组,包含4个元素。 a[0]所代表的一维数组包含的4个元素是: a[0][0]、a[0][1]、a[0][2]、a[0][3] 从二维数组来看,

a代表整个二维数组的首地址, 也就是第0行的首地址,即a[0]地址 a+1代表第1行的首地址,即a[1]地址 a+2代表第2行的首地址,即a[2]地址 实际上a[0]、 a[1]和 a[2]分别表示的是二维的第0行、第1行和第2行。 基于这种认识,把a[0]、 a[1]和 a[2]看成是一维数组名,C语言又规定数组名代表数组的首地址,因此a[0]代表第0行一维数组中第0列元素的地址,即&a[0][0]

依此类推a[1]的值是 &a[1][0] 依此类推a[2]的值是 &a[2][0] 第0行第1列元素的地址可表示为: a[0]+1 在一维数组中, a[0]和*(a+0)等价, a[1]和*(a+1)等价,等 理解: a是二维数组的首地址 a[1]即*(a+1)是第二行的首地址

用地址法如何得到a[0][1]呢? 它的地址表示为 a[0]+1,值表示为*(a[0]+1) 进一步表示为:*(*(a+0)+1) 说明:对二维数组来说, a[i]表示的是一维数组名, a[i]本身不占实际的内存单元,它只是一个地址,表示地址的一种计算方法,如同一维数组x[10]的数组名.

2、指向多维数组的指针变量 (1)指向数组元素的指针变量 main() { int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int *p; for(p=a[0];p<a[0]+12;p++) {if((p-a[0])%4==0)printf(“\n”); printf(“%4d”,*p); }

(2)指向由m个元素组成的一维数组指针变量 输出二维数组任一行任一列元素的值 main() { int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int (*p)[4],i,j; p=a; scanf(“i=%d,j=%d”,&i,&j); printf(“a[%d,%d]=%d\n”,i,j,*(*(p+i)+j)); }

注意(1).* p[4]是指针数组 (2). int a[4]; a有四个元素 (3). int (*p)[4]; *p有4个元素,每个元素都是整型.p所指的对象是有4个整型元素的数组,即p是行指针.应该记住此时p只能指向一个包含4个元素的一维数组,p的值就是该一维数组的首地址. p不能指向一维数组中的第j个元素.

3、多维数组的指针作函数参数 用指针变量作形参以接受实参数组名传来的地址时,有两种方法: (1)用指向变量的指针变量 (2)用指向一维数组的指针变量 通过指针变量存取数组元素速度快,程序简明.用指针变量作形参,可以允许数组的行数不同.因此数组与指针常常是紧密相联的.

10.4 字符串的指针和指向字符串的指针变量 10.4.1 字符串的表示形式 在C中有两种方法 10.4.1 字符串的表示形式 在C中有两种方法 (1)用字符数组存放一个字符串,然后输出该字符串 (2)用字符指针指向一个字符串 显然用%s可以对一个字符串进行整体的输入与输出

main() {char a[]=“I am a boy.”, b[20], *p1,*p2; int i; p1=a;p2=b; for(;*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”); }

10.4.2 字符串指针作函数参数 将一个字符串从一个函数传递到另一个函数,可以用地址传递,用数组名或指针. void str(char *f,char t[ ]){ } main( ) {char a[10],*b; … str(a,b); 10.4.3 对使用字符指针变量和字符数组的讨论 字符指针变量和字符数组实现字符串的存贮与运算,两者之间是有差别的. char str[10]; scanf(“%s”,str); char *a; scanf(“%s”,a);

10.5 函数的指针和指向函数的指针变量 10.5.1 用函数指针变量调用函数 10.5.1 用函数指针变量调用函数 可以用指针变量指向整型变量,字符串,数组,也可以指向一个函数.一个函数在编译时被分配一个入口地址,这个入口地址就称为函数的指针,可以用一个指针变量指向函数,然后通过该指针变量调用此函数.

main() { int a,b,c; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“Max is %d”,c);} int max(int x, int y) { int z; z=x>y?x:y; return(z); }

将main函数改写为: main() { int max(int,int); int (*p)(); int a,b,c; p=max; //将max的入口地址赋给p scanf(“%d,%d”,&a,&b); c=(*p)(a,b); printf(“Max is %d”,c);} int (*p)()定义p是一个指向函数的指针变量,此函数带回整型的返回值.

定义指向函数的指针变量的一般形式 数据类型 (*指针变量)( ); 其它注意事项见教材

10.5.2 用指向函数的指针作函数参数 函数的参数可以是变量,指向变量的指针变量,数组名,指向数组的指针变量,等等 函数指针变量常用的用途之一是把指针作为参数传递到其他函数,是C语言中深入的部分. sub(int (*x1)(int),int (*x2)(int,int)) { int a,b,i=1,j=2; a=(*x1)(i); b=(*x2)(i,j); …….}

10.6 返回指针值的函数 一个函数可以带回一个整型值,字符值,实型值等,也可带回指针型的数据,即地址. 10.6 返回指针值的函数 一个函数可以带回一个整型值,字符值,实型值等,也可带回指针型的数据,即地址. 其本质与以前类似,只是带回的值是指针类型而已 带回指针值的函数,可定义为: 基类型 *函数名(参数表); 如: int *a(int x,int y);

main() {float score[][4]={{60,70,80,90},{50,89,67,88},{ 34,78,90,66}},*p; float *search(float (*ptr)[4]); int i,j; for(i=0;i<3;i++) {p=search(score+i); if(p==*(score+i)) {printf(“No. %d scores:”,i); for(j=0;j<4;j++)printf(“%5.2f”,*(p+j)); printf(“\n”);} }

float *search(float (*ptr)[4]) {int i; float *pt; pt=*(ptr+1); for(i=0;i<4;i++) if(*(*ptr+i)<60) {pt=*ptr; break;} return(pt); }

10.7 指针数组和指向指针的指针 10.7.1 指针数组的概念 一个数组其元素均为指针类型数据,称为指针数组.指针数组中的每一个元素都相当于指针变量.一维指针数组的定义为: 类型名 *数组名[数组长度] 主要用于指向若干个字符串,使字符串的处理更加灵活,如: char *name[ ]={“Tom”,”Bill”,”David”};

10.7.2 指向指针的指针 指针数组的数组名就是一个指针的指针. char **p; 相当于 char *(*p); 指针p是指向一个字符指针变量的变量. *p就是p指向的另一个指针变量 变量的直接访问,间接访问(单级间址,二级间址,多级间址).

10.7.3 指针数组作main函数的形参 指针数组的一个重要作用就是作main函数的形参. main函数的一般形式为: main( ) 实际上main函数可以有形参,如 main(argc,argv) main函数是系统调用的,它的形参对应的实参从何而来呢? 从OS命令中得到:

命令名 参数1 参数2……参数n 利用指针数组作main函数的形参,可以向程序传送命令行参数(这些参数是字符串).由于参数的长度和个数都是不定的,所以用指针数组恰好能满足这一要求.

10.8 有关指针的数据类型和指针运算的小结 10.8.1 有关指针的数据类型的小结 int i; int *p; 10.8.1 有关指针的数据类型的小结 int i; int *p; int a[n]; int *p[n]; int (*p)[n]; int f( ) int *p( ) int (*p)( ) int **p;

10.8.2 指针运算小结 (1)指针变量加(减)一个整数 如:p++,p-i等 (2)指针变量赋值 p=&a; p=array; p=&array[i]; p=max; p1=p2;

(3)指针变量赋空值,表示不指向任何变量 p=NULL; (4)两个指针变量可以相减 指向同一数组的两个不同元素的指针相减是什么意义,而相加呢? (5)两个指针变量可以比较

10.8.3 void指针类型 ANSI增加 void指针类型,可定义一个指针变量,但不指定它是指向哪一种类型数据的,将它的值赋给另一指针变量时要进行强制类型转换. char *p1; void *p2; p1=(char *)p2;

总结 指针变量的优点: 1.提高程序效率 2.可以实现函数改变多个值 3.可以实现灵活的和动态的存贮分配 缺点: 难理解,灵活难以把握,容易出错 作业: 10.2 10.3 10.9 10.13