《C语言教学 第11章.ppt》由会员分享,可在线阅读,更多相关《C语言教学 第11章.ppt(41页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第11章内存的快捷方式指针p 指针概述 p 指针变量 p 指针与函数 p void指针类型 p 综合应用创建简单链表 p 跟我上机 第11章内存的快捷方式指针 指针概述 p 指针变量 p 指针与函数 p void指针类型 p 综合应用创建简单链表 p 跟我上机 第11章内存的快捷方式指针 指针概述 指针变量 p 指针与函数 p void指针类型 p 综合应用创建简单链表 p 跟我上机 第11章内存的快捷方式指针 指针概述 指针变量 指针与函数 p void指针类型 p 综合应用创建简单链表 p 跟我上机 第11章内存的快捷方式指针 指针概述 指针变量 指针与函数 void指针类型 p 综合应用
2、创建简单链表 p 跟我上机 第11章内存的快捷方式指针 指针概述 指针变量 指针与函数 void指针类型 综合应用创建简单链表 p 跟我上机 第11章内存的快捷方式指针 指针概述 指针变量 指针与函数 void指针类型 综合应用创建简单链表 跟我上机 11.1 指针概述11.1.1 内存地址11.1.2 内存和指针11.1.1 内存地址在计算机程序中使用的所有数据,都必须存储在计算机的存储单元中,并且应能从计算机的存储单元中取出。每个存储单位都有唯一的地址,这就好比街道上每家每户都会有自己的门牌号码一样,如下图所示,内存中从地址1234到地址1237中,存储了一个整型数值12,而内存中地址12
3、38中,存储了一个字符“A”。11.1.1 内存地址计算机内存被划分成按顺序编号的内存单元,这就是地址。如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。变量是内存中某一块存储区域的名称,对变量赋值就相当于把值存储到该存储区域中,看下面的表达式:4 字节12341237内存中开辟空间存储数据到内存int total=12;11.1.1 内存地址不同的计算机使用不同的复杂的方式对内存进行编号,通常程序员不需要了解给定的变量具体地址,编译器会处理细节问题,在C语言中,你只需要使用操作运算符&,它就会返回一个对象在内存中的地址,如&total,这个返回的地址指的是该存储
4、区域的起始地址,对变量total来说,就是1234。分析下面代码的结果。int i=12;printf(i的值等于%d,i的地址是n,i,&i);输出结果如下:i的值等于12,i的地址是1245052运行的结果很清晰的显示出变量i的地址,获得变量i的地址是通过取地址运算符&。11.1.2 内存和指针变量的内存地址就是变量的指针。上一小节中变量total的地址1234就是变量i的指针。如果有一个变量专门用来存放另一变量的指针,则它称为指针变量。下图所示的p就是一个指针变量。变量p中存放的是变量i的指针(地址),变量p就是指向i的指针变量。这是变量p的存储单元该单元地址是2600存储的数据是123
5、4这是变量i的存储单元该单元地址是1234存储的数据是1211.1.2 内存和指针定义指针变量的一般形式如下所示:指向数据类型*指针变量名;int i;/*声明变量i*/int*p1;/*声明指向整型变量的指针p1*/char c;/*声明变量c*/char*p2;/*声明指向字符型变量的指针p2*/p1=&i;/*指针赋值*/p2=&c;/*指针赋值*/变量p2变量p2地址是&p2存储数据&c变量c变量p1变量p1地址是&p1存储数据&i变量i11.1.2 内存和指针在定义指针变量时需要注意以下三点:如果有int*p,指针变量名是p,而不是*p,*p是表达式。在定义指针变量时必须明确其指向的
6、数据类型。以下是正确的赋值int i;char c;int*p;p=&i;以下是错误的赋值int i;char c;int*p;p=&c;指针变量中只能存放指针(地址),不要将一个非零数(或任何其他非地址类型的数据)赋给一个指针变量。int*p=2;/*错误的赋值*/int*p=0;/*正确的赋值,表示指针指向空*/11.2 指针变量11.2.1 初识指针变量11.2.2 使用指针变量11.2.3 指针的运算11.2.1 初识指针变量指针变量也是变量,假如该指针变量名叫p,变量p的用途比较特殊,它很无私,它代表的存储单元中存储的是另外一个变量的地址,假如该变量名叫a,可以理解为这个指针变量p指
7、向变量a。当然可以直接访问a从而获得a的数据,也可以间接地通过访问p从而获得a的数据。比如有下面的代码。int i=1;int*p=&i;*p=*p+1;printf(“i=%d,*p=%d”,i,*p);输出结果:i=2,*p=2代码中p=&i,表示指针变量p指向变量i,使用&取地址运算符进行关联的;代码*p=*p+1表示改变指针变量p指向的变量的值,使用的*指针运算符间接访问变量i。11.2.1 初识指针变量【范例范例11-111-1】初始指针变量初始指针变量01#include/*包含标准输入输出头文件*/02 int main(void)03 04 int i,*p1;05 char
8、c,*p2;06 i=12;/*变量i初始化*/07 c=A;/*变量c初始化*/08 p1=&i;/*把变量b的地址赋给p2*/09 p2=&c;/*输出结果*/10 printf(“i=%d,&i=%dn”,i,&i);/*输出i,&i的值*/11 printf(“p1=%d,&p1=%d,*p1=%dn”,p1,&p1,*p1);/*输出p1,&p1,*p1的值*/12 printf(“c=%c,&c=%dn”,c,&c);/*输出c,&c的值*/13 printf(“p2=%d,&p2=%d,*p2=%dn”,p2,&p2,*p2);/*输出p2,&p2,*p2的值*/14 retur
9、n 0;15 11.2.1 初识指针变量【范例范例11-211-2】输入两个整数,存储在变量输入两个整数,存储在变量a a和和b b中,当中,当a a小于小于b b时,使用指针交换时,使用指针交换a a和和b b并输出。并输出。01#include 02 int main(void)03 04 int a,b;05 int*p1,*p2,*p;/*声明三个指针变量*/06 p1=&a;/*初始化p1和p2,p1指向a,p2指向b*/07 p2=&b;08 printf(请输入变量a和变量bn);/*输入a和b的值*/09 scanf(%d%d,&a,&b);10 if(ab)/*当a小于b时交
10、换*/11 12 p=p1;13 p1=p2;14 p2=p;15 16 printf(变量a的值是%d,指针变量p1的值是%d,*p1的值是%dn,a,p1,*p1);/*输出*/17 printf(变量b的值是%d,指针变量p2的值是%d,*p2的值是%dn,b,p2,*p2);/*输出*/18 return 0;19 11.2.1 初识指针变量变量 p2存储数据&a变量 b变量 p1存储数据&b变量 a变量 p2存储数据&b变量 b变量 p1存储数据&a变量 a11.2.2 使用指针变量【范例11-3】输入三个不同的整数,存储在变量a,b和c中,使用指针交换,按照从大到小顺序排序,并输出
11、。11.2.2 使用指针变量【扩展训练】范例中部分代码修改如下:int*p1=&a,*p2=&b,*p;/*声明三个指针变量*/if(*p1*p2)/*当*p1小于*p2时交换*/*p=*p1;*p1=*p2;*p2=*p;11.2.2 使用指针变量代码再次修改如下:int*p1=&a,*p2=&b,p;/*注意,声明两个指针变量,一个一般变量*/if(*p1*p2)/*当*p1小于*p2时交换*/p=*p1;*p1=*p2;*p2=p;11.2.2 使用指针变量【范例11-4】使用函数实现对输入的两个整数按从大到小顺序排序输出。11.2.2 使用指针变量point2存储数据&b变量b2poi
12、nt1存储数据&a变量a1p2存储数据&bpoint2存储数据&b变量b2p1存储数据&apoint1存储数据&a变量a1调用swap函数前,指针指向如图所示调用swap函数,把实参point1和point2传递给了形参p1和p2后,执行swap函数前,指针指向如图所示。11.2.2 使用指针变量p1存储数据&apoint1存储数据&a变量a2p2存储数据&bpoint2存储数据&b变量,b1point2存储数据&b变量b1point1存储数据&a变量a2交换函数执行后,调用并执行swap函数,在还没有返回到主函数前,这里交换的变量a和b的值,point1和point2,p1和p2的指向并没有
13、变,还是指向原来的存储单元,但是a和b变量的值发生了交换,指针指向如图所示。调用swap函数后,主函数输出结果,指针指向如图所示。11.2.2 使用指针变量【拓展训练】02 void swap(int*p1,int*p2)/*形参为指针变量*/03 04 int*temp;/*临时量*/05 temp=p1;/*把指针p1所指向的地址中的值暂存在temp中*/06 p1=p2;/*把指针p2所指向的地址中的值存在p1错指向的地址中*/07 p2=temp;/*把temp中值存储到p2所指向的地址中*/08 printf(swap函数中的输出n);09 printf(*p1=%d,*p1=%dn
14、,*p1,*p2);10 11.2.2 使用指针变量p1存储数据&apoint1存储数据&a变量a1p2存储数据&bpoint2存储数据&b变量b2p2存储数据&apoint1存储数据&a变量a1p1存储数据&bpoint2存储数据&b变量b2调用swap函数,把实参point1和point2传递给了形参p1和p2后,执行swap函数前:交换函数执行后,调用并执行swap函数,在没有返回到主函数前:11.2.3 指针的运算针的运算就是地址的运算。由于这一特点,指针运算不同于普通变量,只允许有限的几种运算。除了可以对指针赋值外,指针的运算还包括移动指针、两个指针相减、指针与指针或指针与地址之间进
15、行比较等。可以通过将指针加减一个整数,或者通过对指针赋值来移动指针。例如:p+n、p-n、p+、p-、+p和-p等,其中n是整数。将指针p加上或者减去一个整数n,表示p向地址增加或减小的方向移动n个元素单元,从而得到一个新的地址,使能访问新地址中的数据。每个数据单元的字节数取决于指针的数据类型。11.2.3 指针的运算如下图所示,变量a,b,c,d和e都是整型数据int类型,它们在内存中占据一块连续的存储区域,地址从1234到1253,每个变量占用4个字节。指针变量p指向变量a,也就是p的值是1234,那么p+1按照上面的描述,表示p向地址增加的方向移动了4个字节,从而指向一个新的地址,这个值
16、就是1238,指向了变量b(变量从a到e占用一块连续的存储区域),同理p+2地址就是1242,再次增加了4个字节,指向了变量c,依次类推。11.2.3 指针的运算【范例11-5】指针变量自身的运算01#include 02 int main(void)03 04 int a=1,b=10;05 int*p1,*p2;06 p1=&a;/*指针赋值*/07 p2=&b;08 printf(p1地址是%d,p1存储的值是%dn,p1,*p1);/*输出*/09 printf(p2地址是%d,p2存储的值是%dn,p2,*p2);/*输出*/10 printf(p1-1地址存储的值是%dn,*(p1
17、-1);/*地址-1后存储的值*/11 printf(p1地址中的值-1后的值是%dn,*p1-1);/*值-1后的值*/12 printf(*(p1-1)的值和*p1-1的值不同n);13 return 0;14 11.3 指针与函数11.3.1 指向函数的指针11.3.2 返回指针的函数11.3.1 指向函数的指针用指针变量可以指向一个函数。函数在程序编译时被分配了一个入口地址。这个函数的入口地址就称为函数的指针。函数指针变量常用的用途之一是把指针作为参数传递到其他函数。指向函数的指针也可以作为参数,以实现函数地址的传递,这样就能够在被调用的函数中使用实参函数。11.3.1 指向函数的指针
18、【范例11-6】指向函数的指针11.3.2 返回指针的函数函数可以返回数值型、字符型、布尔型等数据,也可以带回指针型的数据叫做返回指针值的函数。定义形式为:类型名*函数名(参数表列);例如下式表示的含义是,max函数调用后返回值的数据类型是整型指针。intint*max(int*x,int*y);11.3.2 返回指针的函数【范例11-7】返回指针的函数11.4 VOID指针类型void指针类型,它可以用来指向一个抽象的类型的数据,在将它的值赋给另一指针变量时要进行强制类型转换使之适合于被赋值的变量的类型。通过具体的例子来说明void指针类型的含义和用法,如下代码所示:char*p1;void
19、*p2;p1=(char*)p2;同样可以使用(void*)p1将p1转换成void*类型,如下代码所示:p2=(void*)p1;11.4 VOID指针类型不只对变量可以使用void指针类型,也可以将一个函数定义为void*类型。比如下面代码,表示函数fun返回的是一个地址,它指向空类型,如需要引用此地址,也需要根据情况对之进行类型转换,如对该函数调用得到的地址要进行以下转换。如下代码所示:void*fun(char ch1,char ch2);p1=(char*)fun(ch1,ch2);11.5 综合应用创建简单链表【范例11-8】创建简单链表单链表是一种简单的链表表示,也叫做线性链表。用它来表示线性表时,用指针表示结点间的逻辑关系。因此单链表的一个存储结点包含两部分内容。datalink11.5 综合应用创建简单链表data部分称为数据域,用于存储线性表的一个数据元素;link部分称为指针域,用于存放一个指针,该指针指示该链表下一个结点的开始存储地址。a1a2a3a411.7 跟我上机1.编写C程序,使用指针,实现以下功能:输入三个整数,按照从大到小顺序输出,使用指针变量进行交换。11.7 跟我上机2.编写C,使用指针,实现以下功能:调用函数fun(),调用函数,同时使用返回指针的函数和引用方法,得到函数的最大值和最小值。
限制150内