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

Slides:



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

第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数.
第十章 指针 分析C程序的变量所存放的数据:  数值型数据:整数、实数  字符型数据:字符、字符串 这些变量具有以下性质:
第7章 指针 存储地址的变量的类型就是指针类型 能直接对内存地址操作, 实现动态存储管理 容易产生副作用, 初学者常会出错
第七章 指针 教 材: C程序设计导论 主 讲: 谭 成 予 武汉大学计算机学院.
二级指针与二维数组.
C语言程序设计基础 第10章 指针进阶 刘新国.
10.1 二级指针 10.2 指针与二维数组 10.3 指针的动态存储分配 10.4 函数指针 10.5 main函数的参数
C语言程序设计教程 单位:德州学院计算机系.
第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]的地址;
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
程序设计基础.
第6章 指针 学习目的与要求: 了解指针的概念和相关术语 熟练掌握指向变量、数组和字符串的指针变量的使用方法 了解指向函数的指针变量
指 针 为什么要使用指针 指针变量 指针与数组 返回指针值的函数 动态内存分配 通过指针引用字符串 指向函数的指针 小 结 习 题.
由C程序结构所知,一个完整的C语言程序是由一个且只能有一个main()函数(又称主函数)和若干个其他函数组合而成的。而前面各章仅学习main()函数的编程,本章将介绍其他函数的编程,包括其他函数的定义、调用、参数传递及变量的作用域等。
目录 10.1 指针的基本概念 10.2 指向变量的指针变量 10.3 指向数组的指针变量 10.4 指向函数的指针变量和指针型函数
第八章 指 针 8.1 指针的概念与定义 8.2 指针作函数参数 8.3 指针与数组 8.4 指针与函数 8.5 复杂指针.
第 十 章 指 针.
项目六 用指针优化学生成绩排名 项目要求 项目分析
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
Chap 8 指针 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 指向函数的指针
二维数组的指针表示 与复杂的指针例子 专题研讨课之三.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第8章 指针.
第八章 使用指针.
第十章 指针.
欲穷千里,更上层楼 第十章 指 针 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,
第五章 习题课 电子信息与计算机科学系 曾庆尚.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C++大学基础教程 第6章 指针和引用 北京科技大学 信息基础科学系.
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).
指针 几个概念:  指针也是一种数据类型,具有指针类型的变量,称为指针变量。
第6讲 指针与引用 6.1 指针 6.2 引用.
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。
C程序设计.
第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
Presentation transcript:

第九章 指针 西安工程大学

本章内容: 9.1 指针的概念 9.2 指针变量 9.3 指针和数组 9.4 指针与字符串 9.5 指针与函数 9.6 返回指针值的函数 9.7 指针数组和指向指针的指针

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

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

&与*运算符 含义 两者关系:互为逆运算 理解 10 i_pointer = &i = &(*i_pointer) 含义: 取变量的地址 单目运算符 优先级: 2 结合性:自右向左 含义: 取指针所指向变量的内容 单目运算符 优先级: 2 结合性:自右向左 两者关系:互为逆运算 理解 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 指针变量 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; --间接访问 10 …... 整型变量i 2000 2001 整型变量k 指针变量 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 整型变量k 10

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

[存储类型] 数据类型 *指针名=初始地址值; 3 指针变量的初始化形式 [存储类型] 数据类型 *指针名=初始地址值; 例 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型指针

注意:指针变量必须先赋值,再使用 改正: 例 main( ) { int i=10; int *p; *p=i; printf(“%d”,*p); } …... 2000 2004 2006 2005 整型变量i 10 指针变量p 2001 2002 2003 随机 改正: 例 main( ) { int i=10,k; int *p; p=&k; *p=i; printf(“%d”,*p); }

9.2.2 指针变量的引用 例9.1 指针变量的引用举例 main() { int a; int *pa=&a; a=10; 10 …... f86 f8a f8c f8b 整型变量a 10 指针变量pa f87 f88 f89 main() { int a; int *pa=&a; a=10; printf("a:%d\n",a); printf("*pa:%d\n",*pa); printf("&a:%x(hex)\n",&a); printf("pa:%x(hex)\n",pa); printf("&pa:%x(hex)\n",&pa); } 运行结果: a:10 *pa:10 &a:f86(hex) pa:f86(hex) &pa:f88(hex)

例9.2 输入两个整数,并按从大到小的顺序输出 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); } …... 指针变量p1 指针变量p 2000 2008 2002 2004 2006 指针变量p2 整型变量b 整型变量a 2006 2008 2006 2008 2006 5 9 运行结果:a=5,b=9 max=9,min=5

运行结果:5, 9 9.2.3指针变量作为函数参数 特点:共享内存,“双向”传递——地址传递 例9.3 输入两个整数,并按从大到小的顺序输出 …... 2000 2008 200A 2002 2004 2006 变量a 变量b (main) swap(int x,int y) { int temp; temp=x; x=y; y=temp; } main() { int a,b; scanf("%d,%d",&a,&b); if(a<b) swap(a,b); printf("\n%d,%d\n",a,b); 5 5 9 9 变量temp 变量y 变量x (swap) COPY 值传递 9 5 5 运行结果:5, 9

例9.4 输入两个整数,并按从大到小的顺序输出 运行结果:9,5 swap(int *p1, int *p2) { int p; 5 9 …... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... 整型变量a 整型变量b (main) 指针q1 指针q2 swap(int *p1, int *p2) { int p; p=*p1; *p1=*p2; *p2=p; } main() { int a,b; int *q1,*q2; scanf("%d,%d",&a,&b); q1=&a; q2=&b; if(a<b)swap(q1,q2); printf("\n%d,%d\n",a,b); 5 9 9 5 2000 地址传递 2000 2002 2002 COPY (swap) 指针p1 指针p2 整型p 5 运行结果:9,5

例9.5 输入两个整数,并按从大到小的顺序输出 swap(int x,int y) { int t; 5 t=x; x=y; y=t; } …... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... 整型a 整型b (main) pointer_1 pointer_2 swap(int x,int y) { int t; t=x; x=y; y=t; } main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b) swap(*pointer_1,*pointer_2); printf("\n%d,%d\n",a,b); 5 值传递 9 2000 5 2002 9 COPY (swap) 整型x 整型b 整型t 9 5 5 运行结果:5,9

例9.6 输入两个整数,并按从大到小的顺序输出 swap(int *p1, int *p2) { int *p; 5 p=p1; …... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... 整型a 整型b (main) pointer_1 pointer_2 swap(int *p1, int *p2) { int *p; p=p1; p1=p2; p2=p; } main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b) swap(pointer_1,pointer_2); printf("%d,%d",*pointer_1,*pointer_2); 5 9 2000 2000 2002 2002 COPY (swap) 指针p1 指针p2 指针p **** 2002 2000 2000 运行结果:5,9

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

9.3.2 指针的运算 如 int i, *p; p=1000; () i=p; () 1.指针变量的赋值运算 p=&a; (将变量a地址p) p=array; (将数组array首地址p) p=&array[i]; (将数组元素地址p) p1=p2; (指针变量p2值p1) 不能把一个整数p,也不能把p的值整型变量 如 int i, *p; p=1000; () i=p; ()

2 指针的算术运算 1 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;

3 指针变量的关系运算 若p1和p2指向同一数组,则 p1<p2 表示p1指的元素在前 p1>p2 表示p1指的元素在后 p==NULL或p!=NULL

a[i]  p[i]  *(p+i) *(a+i) [] 变址运算符 a[i]  *(a+i) 9.3.3 数组元素引用方法 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)

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

例9.8 int a[]={1,2,3,4,5,6,7,8,9,10},*p=a,i; 数组元素地址的正确表示: (A)&(a+1) (B)a++ (C)&p (D)&p[i]  数组名是地址常量 p++,p-- () a++,a-- () a+1, *(a+2) ()

for(i=0;i<7;i++,p++) printf("%d",*p); } 例9 通过指针变量输出数组中的元素 main() { int i,*p,a[7]; p=a; for(i=0;i<7;i++) scanf("%d",p++); printf("\n"); for(i=0;i<7;i++,p++) printf("%d",*p); } 5 8 7 6 2 3 1 4 a p p p p p p=a; p p p 指针变量可以指到数组后的内存单元, 在此例中需要注意指针的当前值

9.3.4 数组名作函数参数 数组名作函数参数,是地址传递 数组名作函数参数,实参与形参的对应关系 实参 形参 数组名 指针变量

例9.9.1 将数组a中的n个整数按相反顺序存放 void inv(int x[], int n) { int t,i,j,m=(n-1)/2; for(i=0;i<=m;i++) { j=n-1-i; t=x[i]; x[i]=x[j]; x[j]=t; } main() { int i,a[10]={3,7,9,11,0,6,7,5,4,2}; inv(a,10); printf("The array has been reverted:\n"); for(i=0;i<10;i++) printf("%d,",a[i]); printf("\n"); m=4 i j i j i j i j j i 3 7 9 11 0 6 7 5 4 2 0 1 2 3 4 5 6 7 8 9 2 3 4 7 5 9 11 7 6 本例中实参与形参 均用数组

例9.9.2 将数组a中的n个整数按相反顺序存放 void inv(int *x, int n) 3 7 9 11 6 5 4 2 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] x p=x+m a数组 j i void inv(int *x, int n) { int t,*p,*i,*j,m=(n-1)/2; i=x; j=x+n-1; p=x+m; for(;i<=p;i++,j--) { t=*i; *i=*j; *j=t; } } main() { int i,a[10]={3,7,9,11,0,6,7,5,4,2}; inv(a,10); printf("The array has been reverted:\n"); for(i=0;i<10;i++) printf("%d,",a[i]); printf("\n"); } 2 3 i j 4 7 i j 5 9 i j 7 11 j i 6 实参用数组,形参用指针变量

例9.9.3 将数组a中的n个整数按相反顺序存放 void inv(int *x, int n) { int t,*i,*j,*p,m=(n-1)/2; i=x; j=x+n-1; p=x+m; for(;i<=p;i++,j--) { t=*i; *i=*j; *j=t; } } main() { int i,a[10],*p=a; for(i=0;i<10;i++,p++) scanf("%d",p); p=a; inv(p,10); printf("The array has been reverted:\n"); for(p=a;p<a+10;p++) printf("%d",*p); } 实参与形参均用指针变量

例9.9.4 将数组a中的n个整数按相反顺序存放 void inv(int x[], int n) { int t,i,j,m=(n-1)/2; for(i=0;i<=m;i++) { j=n-1-i; t=x[i]; x[i]=x[j]; x[j]=t; } main() { int i,a[10],*p=a; for(i=0;i<10;i++,p++) scanf("%d",p); p=a; inv(p,10); printf("The array has been reverted:\n"); for(p=arr;p<arr+10;p++) printf("%d ",*p); } 实参用指针变量,形参用数组

9.3.4 指针与二维数组 对于一维数组: (1)数组名array表示数组的首地址,即array[0]的地址; int array[10]; array 对于一维数组: (1)数组名array表示数组的首地址,即array[0]的地址; (2)数组名array是地址常量 (3)array+i是元素array[i]的地址 (4)array[i]  *(array+i)

1 二维数组的地址 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+2 对二维数组 int a[3][4],有 a-----二维数组的首地址,即第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

p 例9.10 用指针变量输出数组元素的值 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 例9.10 用指针变量输出数组元素的值 main() { static 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); }

例9.11 二维数组与指针运算 main() { int a[3][4]={{1,2,3,4},{3,4,5,6},{5,6,7,8}}; int i; int (*p)[4]=a,*q=a[0]; for(i=0;i<3;i++) { if(i==0) (*p)[i+i/2]=*q+1; else p++,++q; } printf("%d,",a[i][i]); printf("%d,%d\n",*((int *)p),*q); p q p q p q 1 2 3 4 5 6 7 8 2 运行结果: 2,4,7,5,3

若int a[3][4]; int (*p1)[4]=a; int *p2=a[0]; 2 二维数组的指针作为函数参数 实参 形参 数组名int x[][4] 指针变量int (*q)[4] 指针变量int (*q)[4] 数组名a 指针变量p1 若int a[3][4]; int (*p1)[4]=a; int *p2=a[0]; 指针变量p2 指针变量int *q

例9.12 输入3个学生4门课的成绩,计算总平均分,并输出第n个学生成绩 void average(float *p,int n) { float *p_end, sum=0,aver; p_end=p+n-1; for(;p<=p_end;p++) sum=sum+(*p); aver=sum/n; printf("average=%5.2f\n",aver); } void search(float (*p)[4], int n) { int i; printf(" No.%d :\n",n); for(i=0;i<4;i++) printf("%5.2f ",*(*(p+n)+i)); main() { void average(float *p,int n); void search(float (*p)[4],int n); float score[3][4]= {{65,67,79,60},{80,87,90,81}, {90,99,100,98}}; average(*score,12); search(score,2); } 函数说明 p float p[][4] p 65 52 79 60 80 87 90 81 99 100 98 等价于 p[n][i]

9.4 指针与字符串 1 字符串的表示形式 例14 用字符数组存放一个字符串并输出 main( ) l o v e C h i string[0] string[1] string[2] string[3] string[4] string[5] string[6] string[7] string[8] string[9] string string[10] string[11] string[12] string[13] n ! a \0 例14 用字符数组存放一个字符串并输出 main( ) { char string[]=“I love China!”; printf(“%s\n”,string); printf(“%s\n”,string+7); }

例9.14 用字符指针指向一个字符串 字符指针初始化:把字符串首地址赋给string  char *string; l o v e C h i string n ! a \0 例9.14 用字符指针指向一个字符串 字符指针初始化:把字符串首地址赋给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

2 字符串指针作函数参数 void copy_string(char from[],char to[]) { int i=0; 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 2 字符串指针作函数参数 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); 例9.15 用函数调用实现字符串复制 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)用字符指针变量作参数

3 字符指针变量与字符数组的讨论 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

char str[]={“Hello!”}; () 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}; () scanf(“%s”,str); printf(“%s”,str); gets(str); puts(str);

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

用指针变量调用函数: 一般方法: 例9.16 求a和b两个数中的较大者。 main() { int max(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 max(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); 例9.16 求a和b两个数中的较大者。

9.5.2 用函数指针变量作函数参数 例9.17 用函数指针变量作参数,求最大值、最小值和两数之和 void main() 例9.17 用函数指针变量作参数,求最大值、最小值和两数之和 void main() { int a,b,max(int,int), min(int,int),add(int,int); void process(int,int,int (*fun)()); scanf("%d,%d",&a,&b); process(a,b,max); process(a,b,min); process(a,b,add); } void process(int x,int y,int (*fun)()) { int result; result=(*fun)(x,y); printf("%d\n",result); max(int x,int y) { printf(“max=”); return(x>y?x:y); min(int x,int y) { printf(“min=”); return(x<y?x:y); add(int x,int y) { printf(“sum=”); return(x+y);

9.6 返回指针值的函数 函数定义形式: 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("%5.2f\t",*(p+i)); } float *search(float (*pointer)[4], int n) { float *pt; pt=*(pointer+n); return(pt); 9.6 返回指针值的函数 函数定义形式: 类型标识符 *函数名(参数表); 例 int *f(int x, int y) 例9.18 指针函数实现:有若干学生成绩,要求输入学生序号后,能输出其全部成绩 p p p p pointer pointer+1 34 78 90 66 56 89 67 88 60 70 80 score数组

例9.19.1 写一个函数,求两个int型变量中居于较大值的变量的地址 …... 2000 2008 200A 2002 2004 2006 int *f1(int *x,int *y) { if(*x>*y) return x; else return y; } main() { int a=2,b=3; int *p; p=f1(&a, &b); printf("%d\n",*p); 变量a 变量b (main) 指针变量p COPY 2 3 2002 ** 指针变量y 指针变量x (f1) 2000 2002

例9.19.2 写一个函数,求两个int型变量中居于较大值的变量的地址 …... 2000 2008 200A 2002 2004 2006 int *f3(int x,int y) { if(x>y) return &x; else return &y; } main() { int a=2,b=3; int *p; p=f3(a, b); printf("%d\n",*p); 变量a 变量b (main) 指针变量p COPY 2 3 200A ** 变量y 变量x (f3) 2 3

9.7 指针数组和多级指针 9.7.1 指针数组 定义:数组中的元素为指针类型的数据. 定义形式:[存储类型] 数据类型 *数组名[数组长度]; 例 int *p[4]; 指针数组赋值与初始化 指针本身的存储类型 指针所指向变量的数据类型 区分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 赋值: 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

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”}; 二维数组存储空间固定 字符指针数组相当于可变列长的二维数组 分配内存单元=数组元素个数*2+各字符串长度 指针数组元素的作用相当于二维数组的行名 但指针数组中元素是指针变量 二维数组的行名是地址常量

例9.20 将若干字符串按字母顺序由小到大输出 k k j j j j i=0 main() { void sort(char *name[],int n), print(char *name[],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer "}; int n=5; sort(name,n); print(name,n); } void sort(char *name[],int n) { char *temp; int i,j,k; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} 例9.20 将若干字符串按字母顺序由小到大输出 name k name[0] Follow me k j name[1] BASIC j name[2] Great Wall j name[3] FORTRAN j name[4] Computer i=0

k j k j k j i=1 name name[0] Follow me name[1] BASIC name[2] Great Wall k j name[3] FORTRAN k j name[4] Computer i=1

9.7.2 多级指针(指向指针的指针) 一级指针:指针变量中存放目标变量的地址 例 int *p; int i=3; p=&i; *p=5; 单级间接寻址 二级指针:指针变量中存放一级指针变量的地址 例 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是二级指针,不能用变量地址为其赋值

char *name[]={"hello","good","world","bye",""}; p=name+1; 例9.21 用二级指针处理字符串 用*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 **q完全等价;但作为变量定义两者不同 系统只给p分配能保存一个指针值的内存区;而给q分配10块内存区,每块可保存一个指针值

C:\TC> copy[.exe] source.c temp.c 9.7.3 指针数组作main函数的形参 Main函数可以有参数 ,例如 实在参数是和命令行一起给出,命令行格式: 命令名 参数1 参数2………参数n 命令行参数传递 main(int argc, char *argv[]) { ……… } C:\TC> copy[.exe] source.c temp.c 形参名任意 命令行中参数个数 元素指向命令行参数 中各字符串首地址 命令行实参 main(形参) 系统自动调用 main函数时传递 有3个字符串参数的命令行 第一个参数: main所在的可执行文件名

例9.22 输出命令行参数 main(int argc, char *argv[]) 例9.22 输出命令行参数 main(int argc, char *argv[]) { while(argc>1) { ++argv; printf("%s\n",*argv); --argc; } main(int argc, char *argv[]) { while(argc-->0) printf("%s\n",*argv++); } argv[0] argv[1] argv[2] char *argv[] world test hello argv argc=3 运行结果:test hello world! 1. 编译、链接test.c,生成可执行文件test.exe 2. 在DOS状态下运行(test.exe所在路径下) 运行结果:hello world! 例如: C:\TC> test[.exe] hello world!

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

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