指 针 为什么要使用指针 指针变量 指针与数组 返回指针值的函数 动态内存分配 通过指针引用字符串 指向函数的指针 小 结 习 题.

Slides:



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

第七章 指针 计算机公共教学部.
第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数.
第十章 指针 分析C程序的变量所存放的数据:  数值型数据:整数、实数  字符型数据:字符、字符串 这些变量具有以下性质:
第7章 指针 存储地址的变量的类型就是指针类型 能直接对内存地址操作, 实现动态存储管理 容易产生副作用, 初学者常会出错
第七章 指针 教 材: C程序设计导论 主 讲: 谭 成 予 武汉大学计算机学院.
二级指针与二维数组.
C语言程序设计基础 第10章 指针进阶 刘新国.
10.1 二级指针 10.2 指针与二维数组 10.3 指针的动态存储分配 10.4 函数指针 10.5 main函数的参数
C语言程序设计教程 单位:德州学院计算机系.
第 6 章 第 6 章 指 针 指 针 1.
第8章 指针 ● 8.1 指针简介 ● 8.2 指针变量的操作 ● 8.3 数组与指针 ● 8.4 二维数组与指针 ●本章小结 ●本章练习.
一维数组 乾坤以有亲可久; 君子以厚德载物。.
C语言程序设计.
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 指针应用实例
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
程序设计基础.
第6章 指针 学习目的与要求: 了解指针的概念和相关术语 熟练掌握指向变量、数组和字符串的指针变量的使用方法 了解指向函数的指针变量
目录 10.1 指针的基本概念 10.2 指向变量的指针变量 10.3 指向数组的指针变量 10.4 指向函数的指针变量和指针型函数
第八章 指 针 8.1 指针的概念与定义 8.2 指针作函数参数 8.3 指针与数组 8.4 指针与函数 8.5 复杂指针.
第 十 章 指 针.
项目六 用指针优化学生成绩排名 项目要求 项目分析
目录 第八章 数组 1 简单学生成绩管理系统的开发 2 一维数组 3 多维数组 4 字符数组 5 数组作函数参数.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
Introduction to the C Programming Language
C语言程序设计 李祥.
第八章 函数.
辅导课程六.
第7章 函 数 为什么要使用函数? 函数定义、调用、声明 局部变量和全局变量 变量的存储类别 内部函数和外部函数 函数的嵌套调用和递归调用
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
二维数组的指针表示 与复杂的指针例子 专题研讨课之三.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第8章 指针.
第八章 使用指针.
第十章 指针.
欲穷千里,更上层楼 第十章 指 针 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,
第五章 习题课 电子信息与计算机科学系 曾庆尚.
第五章 指针 5.1 指针的概念 5.2 指针与数组 5.3 字符串指针.
9.1 地址、指针和变量 9.2 指针运算 9.3 指针与数组 9.4 函数与指针 9.5 程序综合举例 9.6 上机实训.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
C语言复习3----指针.
第一章 程序设计和C语言 主讲人:高晓娟 计算机学院.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
C语言大学实用教程 第7章 指针 西南财经大学经济信息工程学院 刘家芬
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
第6讲 指针与引用 6.1 指针 6.2 引用.
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。
第4章 Excel电子表格制作软件 4.4 函数(一).
第九章 指针.
第九节 赋值运算符和赋值表达式.
3.16 枚举算法及其程序实现 ——数组的作用.
第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程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第八章 指 针 北京邮电大学出版社.
C语言基础学习 从外行到入门.
Presentation transcript:

指 针 为什么要使用指针 指针变量 指针与数组 返回指针值的函数 动态内存分配 通过指针引用字符串 指向函数的指针 小 结 习 题

能否通过变量地址访问数据? 例 冒泡排序 void sort(int a[], int n) { int i,j; void main() 例 冒泡排序 //函数:输入数组a[n] void sort(int a[], int n) { int i,j; } void main() { int i,j,a[10]; printf("input 10 numbers:\n"); input(a,10); output(a,10); } n-1; n-1-j; for(j=0;j<9;j++) for(i=0;i< 9-j ;i++) if(a[i]>a[i+1]) { t=a[i]; a[i]=a[i+1]; a[i+1]=t; } swap(a[i],a[i+1]); //函数:对数组a[n]冒泡排序 sort(a,10); 错!实参对形参 值传递 形参改变不影响实参 地址 问题引入:使用swap函数并不能交换(a[i],a[i+1]); 借鉴数组名作参数的方法=》需要地址传递 思考: (1)如何得到一个变量的地址? & (2)能否用一个变量来存放地址? 如何得到一个变量的地址? void swap(int x, int y) { int t; t=x; x=y; y=t; }

运算符 & 和 * 如何得到一个变量的地址? 运算符 & 功能:求变量的内存地址. 如何保存一个变量的地址? 指针变量 运算符 * 运算符 & 功能:求变量的内存地址. void sort(int a[],int n) { int i,j,t; for(j=0;j<n-1;j++) for(i=0;i<n-1-j;i++) if(a[i]>a[i+1]) swap(a[i],a[i+1]); } int i; int *p; scanf(“%d”, &i); p=&i; swap(&a[i], &a[i+1]); 如何保存一个变量的地址? 指针变量 运算符 * 功能:定义保存地址的变量 void swap( int x, int y) { int t; t=x; x=y; y=t; } void swap(int *p1, int *p2);

指针概念 3 6 ... .. 变量i 变量j 变量k 3010 2000 2002 2004 变量的值 内存地址 例:有定义: int i=3,j=6,k, *pointer; pointer=&i; k=i; k=*p; // 直接访问: 通过变量名i存取变量值 间接访问 (1)先在地址变量中找到i的地址 (2)再根据地址找到变量i,存取变量值。 3 指向 找到p指向的单元的内容 2000 变量pointer 变量pointer为指针变量,存放变量i的地址,称: pointer指向 i

指针变量的定义 1. 定义方式: 类型标识符 *指针变量名; 例:float *p1; (定义p1为指向float型变量的指针变量) 1. 定义方式: 类型标识符 *指针变量名; 例:float *p1; (定义p1为指向float型变量的指针变量) char *p2; (定义p2为指向char型变量的指针变量) 2. 指针变量的三要素: 指针变量的类型: 和其所指变量的类型一致; 指针变量的值:另一个变量在内存的地址; 指针变量的名字: 同普通变量。 例:int a=10, *p p=&a; 10 a a的地址 p 1000 3000 &a

指针变量的引用 指针变量名 = 某一地址; 例如: int i=10,*p,*q; p=&i; //方式1: 指针变量=&变量; 指向 10 i i的地址 p 1000 3000 &i q i的地址 & i q

指针举例 c=a+b A0801 指针变量定义及运算 main(){ int a=10,b=20,c; int *p,*q; p=&a; q=&b; c=*p+*q; printf("a=%d b=%d c=%d",a,b,c); } 10 20 a b c p q 30 c=a+b *p:指针p所指向的单元中的值10 *q:指针q所指向的空间中的值20 输出结果: a=10 b=20 c=30

指针举例 swap能交换sort函数中的变量吗? void sort(int a[],int n) { int i,j,t; for(j=0;j<n-1;j++) for(i=0;i<n-1-j;i++) if(a[i]>a[i+1]) swap(a[i],a[i+1]); } void swap( int x, int y) { int t; t=x; x=y; y=t; void sort(int a[],int n) { int i,j,t; for(j=0;j<n-1;j++) for(i=0;i<n-1-j;i++) if(a[i]>a[i+1]) swap(&a[i], &a[i+1]); } void swap(int *pa, int *pb); { int t; t=x; x=y; y=t; swap能交换sort函数中的变量吗? t=*pa; *pa=*pb; *pb=t;

值传递 a b 5 9 x y 9 y 5 x b a 9 5 变量x,y,t 释放 变量a,b的值不改变 9 5 5 5 9 b a main中 9 b 5 a 变量x,y,t 释放 变量a,b的值不改变 9 5 (参数传递初始) t a b void f(int x,int y)  {  int t;  t=x;  x=y;   y=t;   }  5 调用 f 函数 f 函数结束

地址传递 5 9 9 &b 5 &a 9 5 变量a,b的值改变,释放变量 t 和指针变量pa,pb 9 5 5 pa a a pa a (参数传递初始) t &a &b swap(int *pa,int *pb) { int t; t=*pa; *pa=*pb; *pb=t; } 5 调用swap函数 swap函数结束

指针变量作为函数参数 A0802例: 指针实现两数交换的函数 传递变量a,b的地址 void swap(int *pa,int *pb) { int t; t=*pa; *pa=*pb; *pb=t; } void main() {void swap(int *pa,int *pb); int a,b; scanf("%d,%d",&a,&b); swap(&a,&b); printf("\n%d,%d\n",a,b); } 传递变量a,b的地址 从键盘输入:5,10 输出: 10,5 (改变了a、b的值)

指针变量作为函数参数 A0802例: 指针实现两数交换的函数 int *p1,*p2; p1=&a; p2=&b; p1,p2 main() {void swap(int *pa,int *pb); int a,b; scanf("%d,%d",&a,&b); swap(&a,&b); printf("\n%d,%d\n",a,b); } void swap(int *pa,int *pb) { int t; t=*pa; *pa=*pb; *pb=t; } int *p1,*p2; p1=&a; p2=&b; p1,p2 从键盘输入:5,10 输出: 10,5 (改变了a、b的值) 传递变量a,b的地址

指针练习 main() { int *p1,*p2,*p,a,b; a=5;b=9; p1=&a;p2=&b; ① if (a<b) }  ④  printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d\n",*p1,*p2); }

[例]不改变变量的内容,按大小顺序输出 main() { int *p1,*p2,*p,a,b; a=5;b=9; p1=&a;p2=&b; ① p1 5 a p if (a<b) { p=p1;  ② p1=p2;  ③ p2 9 b p2=p; }  ④  printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d\n",*p1,*p2); } a=5, b=9 max=9, min=5 (仅仅按大小顺序输出,但是不改变a、b的值)

指针与数组 例 对一个班的所有学生求某门课程的平均成绩 问题:每个班的学生人数不同 => 动态输入班级人数 通过指针引用数组 例 对一个班的所有学生求某门课程的平均成绩 问题:每个班的学生人数不同 => 动态输入班级人数 数组定义: 类型 数组名[常量表达式]; 例:int a[30]; 1 代码 2 静态数据 3 动态数据 4 自由空间(堆heap) 地址常量 通过指针引用数组 动态分配一块存储空间,返回该存储空间的首地址(指针) 返回指针的函数 数组定义时要求 地址变量

指针的运算 1.算术运算 p 1000 例如: int *p,i; 1001 i char *q , c; 1002 p=&i; …... 2000 2001 c q p=p+1:新p指向下一元素 加一个类型的字节数,而不是加1 如:int 占 2个字节, char占1个字节。

指向数组元素的指针 int a[10]={0,2,4,6}; int *p, t1, t2; p=&a[0]; p=a; t1=*p+1; 地址 1000 1002 1004 1005 … 1018 p= p+1 p+2 p指向的单元内容+1,即a[0]+1 p+1指向的单元的内容, 即a[1] t1=1 t2=2 p+9

指向数组元素的指针 2 通过指针引用数组元素 a数组 a[0] a[1] a[2] a[i] a[9] p=a p+1 p+i p+9 2 通过指针引用数组元素 定义 int a[5], *p; p=a; 引用一个数组元素有两种方法: (1)下标法:a[i]; (2)指针法: *(p+i) 下标法: a[0] a[1] a[2] a[3] a[4] 指针法: *p *(p+1) *(p+2) *(p+3) *(p+4) 各元素地址 p p+1 p+2 p+3 p+4

指向数组元素的指针 A0803例 :用指针的方法访问数组 void main() { int array[10] ,i, *p; p=a p+1 p+i p+9 p+2 p+3 A0803例 :用指针的方法访问数组 void main() { int array[10] ,i, *p; for (i=0;i<10;i++) scanf("%d",&a[i]); p=array; p+i p++ p=array; for (i=0;i<10;i++) printf("%d", a[i] ); } for (p=array;p<(array+10);p++) printf("%d",*p); *(p+i) *(p++)

访问数组 数组名本身就代表数组地址,故通过数组名也可以访问数组 例如: int a[10],*p; p=a; &a[0] p 1 3 15 变量的地址 1 3 15 17 19 a[0] : a[9] 变量的值 例如: int a[10],*p; p=a; a+1或p+1 a+9或p+9

访问数组 若有数组及指针定义 int a[5],*p=a; 下标法: a[0] a[1] a[2] a[3] a[4] 指针法: *p *(p+1) *(p+2) *(p+3) *(p+4) *a *(a+1) *(a+2) *(a+3) *(a+4) 各元素地址 p p+1 p+2 p+3 p+4 a a+1 a+2 a+3 a+4 注意:p++合法;但a++不合法 因为a是数组名,代表数组首地址,是常数地址 p是指针变量

指针练习2 10 30 (2)写出下面程序输出结果 main() { int a[3],*p=a; a[0]=10;a[1]=20;a[2]=30; printf(“%d\n”,*p++); printf(“%d\n”,*++p); } 先使用*p的值a[0], 再让p++指向a[1] 先让p+1指向a[2],再使用*p的值a[2] 10 30

指针练习3 4, 5, 7 (3) main() { int a[]={1,2,3,4,5}; int *p=a+3; printf(“%d,%d,%d\n”,*p,*(p+1),*p+3); } 4, 5, 7

返回指针的函数 1.定义: 类型标识符 *函数名(参数表); 函数名前有*,是指针函数,函数的返回值是指针类型 1.定义: 类型标识符 *函数名(参数表); 函数名前有*,是指针函数,函数的返回值是指针类型 int *max(int x,int y) { if(x<y) return(&x); else return(&y); } main() { int a,b,*p; int *max( ); scanf(“%d,%d”,&a,&b); p=max(a,b); printf(“max=%d”,*p); } 键盘输入: 1,2 屏幕输出: max=2

内存动态分配函数 #include<stdlib.h> 1. malloc 函数 内存动态存储区中分配一个长度为size的连续空间 2. free函数 释放空间 3. calloc函数 内存动态存储区中分配n个 长度为size的连续空间 引入:

创建动态长度数组--- calloc函数 A0804 动态输入班级人数,及学生成绩,求平均成绩 内存动态存储区中分配n个长度为size的连续空间 void main() { int n,i, *p; float aver; printf("请输入班级人数:"); scanf("%d",&n); p=calloc(n,sizeof (int)); printf("请输入学生成绩:"); printf("\n 平均成绩: %f\n", aver); } void inputarray( int *p, int n) { int i; } for(i=0;i<n;i++) scanf("%d",p+i); inputarray(p,n); float average( int *p, int n) { int i; return aver; } for(i=0,aver=0;i<n;i++) aver=aver+*(p+i); aver=aver/n; average(p,n);

多维数组的指针 1. 定义引用形式与指向一维数组的指针类似 例如: int a[3][4],*p; p=&a[2][3]; 2000 2002 2004 2006 2008 2010 2012 2014 2016 2018 2020 2022 a a+1 a+2 a[0]+1 a[0]+2 a[0]+3 行地址,元素地址的表示 2. 行列地址表示 若有定义:int a[3][4]; 下图表格中的数字表示每个元素的地址值

指针与字符串 例:char *s=“I Love China!” ; /*初始化s*/ s=string; /*字符数组赋值给字符串指针*/ 跟我来! 1. 字符串的表示形式 用字符数组实现(已学过): 例:char string[ ]="I Love China!"; ! e 串首址 I v ... s L o \0 用字符指针实现: 字符指针变量的定义:char *p ; 赋值: 指针=串中某一字符地址; 例:char *s=“I Love China!” ; /*初始化s*/ s=string; /*字符数组赋值给字符串指针*/ s=“ I love China!”; /*字符串整体赋值*/

指针与字符串 A0805例 :用字符指针逐个输出字符串中的字符 #include<stdio.h> void main() { char string[ ]="I like C language!"; char *p; for(p=string; *p!=‘\0’; p++) printf(“%c”,*p); printf(“\n”); } ! e 串首址 I k ... p L i \0

指 针 数 组 1. 概念:一个数组中的每个元素都是指针类型 2. 定义:数据类型 *数组名[数组长度] 2. 定义:数据类型 *数组名[数组长度] 例:int *p[4] /* 4个指向整形的指针构成的数组*/ char *p[3] /* 3个指向字符串的指针构成的数组*/ 每个指针变量 所指向的类型

指针数组实例 American China Japan A C J main() m h a { int i; char *sa[]={“American”,”China”,”Japan”}; for(i=0;i<3;i++) printf(“%s\t”,sa[i]); printf(“\n”); for(i=0;i<3;i++) printf(“%c\t”, *sa[i] ); } m h a *(sa[i]+1)

指向指针的指针 ------指向指针变量的指针. 定义形式: 类型 **变量名; 例如: int i,*p,**q; i=30; p=&i; 定义形式: 类型 **变量名; 例如: int i,*p,**q; i=30; p=&i; q=&p; printf(“%d”, i); printf(“%d”, *p); printf(“%d”, **q); 1000 2000 1001 3000 i p q 内存示意图: 30

指向函数的指针 1.函数名代表函数的入口地址 max 2.指向函数的指针的定义方式: 类型 (*指针变量名)( ); p 函数 数 … 类型 (*指针变量名)( ); max p 函数 数 … 例:设有函数定义: int max(…) {…….} int (*p) ( ); /*定义指向函数的指针变量*/ p=max; /* 使p指向max函数的入口地址,可以通过(*p)( 参数)来调用max函数*/

指向函数的指针 c=(*p)(a,b); 例 : 输入两个整形,返回最大值 main( ) int max(int x, int y) 例 : 输入两个整形,返回最大值 main( ) { int max(int,int); int (*p) ( ); //指向函数的指针变量 int a,b,c; p=max; /*指针变量赋值*/ scanf("%d,%d",&a,&b); c=max( a, b) ; /*调用函数*/ printf("a=%d,b=%d,max=%d",a,b,c); } int max(int x, int y) { int z; if (x>y) z=x; else z=y; return (z); } c=(*p)(a,b);

命令行参数1 main函数可以有参数,使用指针数组作为形参 main(int argc, char *argv[]) { 函数体; } 字符串指针数组 存放接收的参数 argv[i] 指向一个参数 其中argv[0]指向命令名 接收到的 参数个数 main函数的实参和命令一起给出,格式如下: 命令名 参数1 参数2 参数3 ……. 说明:命令名 是main函数所在的文件名

命令行参数2 程序调试运行步骤 如源文件保存为 limain.c 保存路径为 D:\C 经过编译生成 limain.obj 经过链接生成 limain.exe 例 :带参数的main函数。 main(int argc, char *argv[]) { int i; for(i=1;i<argc;i++) printf("%s\n",argv[i]); } 在DOS下输出 java c++ 打开DOS环境,进入D:\C D:C\>limain java c++

命令行参数3 argc=3 例 :带参数的main函数。 main(int argc, char *argv[]) { int i; for(i=1;i<argc;i++) printf("%s\n",argv[i]); } 打开DOS环境,进入D:\C D:C\>limain java c++ argv argv+1 argv+2 argv[0] argv[1] argv[2] limain\0 java\0 c++\0 main(int argc, char *argv[]) { while( argc>1) { ++argv; printf(“%s\n”, *argv); --argc ; } argc=3 在DOS下输出 java c++

指针小结 int *p1 ; /*指向整形变量,整形数组的指针变量*/ char *p /*指向字符串的指针变量*/ int *a(int x,float y) /*返回指针值的函数*/ {…函数体…} int *p[4] /* 指向整形的指针数组*/ char *p[4] /* 指向字符串的指针数组*/ int **q /*指向指针变量的指针*/

指针 习题 B0801(习题8.5)有n个人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位? B0802 (习题8.17)自己写一个函数,实现字符串的比较