资源描述
,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,ASP.NET 3.5网站开发从入门到精通,*,单击此处编辑母版标题样式,第,11,章,内存的快捷方式,指针,指针概述,指针变量,指针与函数,void,指针类型,综合应用,创建简单链表,跟我上机,第,11,章,内存的快捷方式,指针,指针概述,指针变量,指针与函数,void,指针类型,综合应用,创建简单链表,跟我上机,第,11,章,内存的快捷方式,指针,指针概述,指针变量,指针与函数,void,指针类型,综合应用,创建简单链表,跟我上机,第,11,章,内存的快捷方式,指针,指针概述,指针变量,指针与函数,void,指针类型,综合应用,创建简单链表,跟我上机,第,11,章,内存的快捷方式,指针,指针概述,指针变量,指针与函数,void,指针类型,综合应用,创建简单链表,跟我上机,第,11,章,内存的快捷方式,指针,指针概述,指针变量,指针与函数,void,指针类型,综合应用,创建简单链表,跟我上机,第,11,章,内存的快捷方式,指针,指针概述,指针变量,指针与函数,void,指针类型,综合应用,创建简单链表,跟我上机,11.1,指针概述,11.1.1,内存地址,11.1.2,内存和指针,11.1.1,内存地址,在计算机程序中使用的所有数据,都必须存储在计算机的存储单元中,并且应能从计算机的存储单元中取出。每个存储单位都有唯一的地址,这就好比街道上每家每户都会有自己的门牌号码一样,如下图所示,内存中从地址,1234,到地址,1237,中,存储了一个整型数值,12,,而内存中地址,1238,中,存储了一个字符,“,A,”,。,11.1.1,内存地址,计算机内存被划分成按顺序编号的内存单元,这就是地址。如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。,变量是内存中某一块存储区域的名称,对变量赋值就相当于把值存储到该存储区域中,看下面的表达式:,4,字节,1234,1237,内存中开辟空间,存储数据到内存,int total=12,;,11.1.1,内存地址,不同的计算机使用不同的复杂的方式对内存进行编号,通常程序员不需要了解给定的变量具体地址,编译器会处理细节问题,在,C,语言中,你只需要使用操作运算符,&,,它就会返回一个对象在内存中的地址,如,&total,,这个返回的地址指的是该存储区域的起始地址,对变量,total,来说,就是,1234,。,分析下面代码的结果。,int i=12;,printf(i,的值等于,%d,i,的地址是,n,i,输出结果如下:,i,的值等于,12,,,i,的地址是,1245052,运行的结果很清晰的显示出变量,i,的地址,获得变量,i,的地址是通过取地址运算符,&,。,11.1.2,内存和指针,变量的内存地址就是变量的指针。上一小节中变量,total,的地址,1234,就是变量,i,的指针。如果有一个变量专门用来存放另一变量的指针,则它称为指针变量。下图所示的,p,就是一个指针变量。变量,p,中存放的是变量,i,的指针(地址),变量,p,就是指向,i,的指针变量。,这是变量,p,的存储单元,该单元地址是,2600,存储的数据是,1234,这是变量,i,的存储单元,该单元地址是,1234,存储的数据是,12,11.1.2,内存和指针,定义指针变量的一般形式如下所示:,指向数据类型*指针变量名;,int i,;,/*,声明变量,i*/,int*p1;/*,声明指向整型变量的指针,p1*/,char c,;,/*,声明变量,c*/,char*p2;/*,声明指向字符型变量的指针,p2*/,p1=/*,指针赋值*,/,p2=/*,指针赋值*,/,变量,p2,变量,p2,地址是,&p2,存储数据,&c,变量,c,变量,p1,变量,p1,地址是,&p1,存储数据,&i,变量,i,11.1.2,内存和指针,在定义指针变量时需要注意以下三点:,如果有,int*p,,指针变量名是,p,,而不是*,p,,*,p,是表达式。,在定义指针变量时必须明确其指向的数据类型。,以下是正确的赋值,int i;,char c;,int*p;,p=,以下是错误的赋值,int i;,char c;,int*p;,p=,指针变量中只能存放指针,(,地址,),,不要将一个非零数,(,或任何其他非地址类型的数据,),赋给一个指针变量。,int*p=2;/*,错误的赋值*,/,int*p=0;/*,正确的赋值,表示指针指向空*,/,11.2,指针变量,11.2.1,初识指针变量,11.2.2,使用指针变量,11.2.3,指针的运算,11.2.1,初识指针变量,指针变量也是变量,假如该指针变量名叫,p,,变量,p,的用途比较特殊,它很无私,它代表的存储单元中存储的是另外一个变量的地址,假如该变量名叫,a,,可以理解为这个指针变量,p,指向变量,a,。当然可以直接访问,a,从而获得,a,的数据,也可以间接地通过访问,p,从而获得,a,的数据。,比如有下面的代码。,int i=1;,int*p=,*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-1】,初始指针变量,01#include/*,包含标准输入输出头文件*,/,02 int main(void),03 ,04 int i,*p1;,05 char c,*p2;,06 i=12;/*,变量,i,初始化*,/,07 c=,A,;/*,变量,c,初始化*,/,08 p1=/*,把变量,b,的地址赋给,p2*/,09 p2=/*,输出结果*,/,10 printf(,“,i=%d,&i=%dn,”,i,/*,输出,i,,,&i,的值*,/,11 printf(,“,p1=%d,&p1=%d,*p1=%dn,”,p1,/*,输出,p1,,,&p1,,*,p1,的值*,/,12 printf(,“,c=%c,&c=%dn,”,c,/*,输出,c,,,&c,的值*,/,13 printf(,“,p2=%d,&p2=%d,*p2=%dn,”,p2,/*,输出,p2,,,&p2,,*,p2,的值*,/,14 return 0,;,15 ,11.2.1,初识指针变量,【,范例,11-2】,输入两个整数,存储在变量,a,和,b,中,当,a,小于,b,时,使用指针交换,a,和,b,并输出。,01#include,02 int main(void),03 ,04 int a,b;,05 int*p1,*p2,*p;/*,声明三个指针变量*,/,06 p1=/*,初始化,p1,和,p2,,,p1,指向,a,,,p2,指向,b*/,07 p2=,08 printf(,请输入变量,a,和变量,bn);/*,输入,a,和,b,的值*,/,09 scanf(%d%d,10 if(ab)/*,当,a,小于,b,时交换*,/,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,变量,a,11.2.2,使用指针变量,【,范例,11-3】,输入三个不同的整数,存储在变量,a,,,b,和,c,中,使用指针交换,按照从大到小顺序排序,并输出。,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,变量,b,2,point1,存储数据,&a,变量,a,1,p2,存储数据,&b,point2,存储数据,&b,变量,b,2,p1,存储数据,&a,point1,存储数据,&a,变量,a,1,调用,swap,函数前,指针指向如图所示,调用,swap,函数,把实参,point1,和,point2,传递给了形参,p1,和,p2,后,执行,swap,函数前,指针指向如图所示。,11.2.2,使用指针变量,p1,存储数据,&a,point1,存储数据,&a,变量,a,2,p2,存储数据,&b,point2,存储数据,&b,变量,b,1,point2,存储数据,&b,变量,b,1,point1,存储数据,&a,变量,a,2,交换函数执行后,调用并执行,swap,函数,,在,还没有返回到主函数前,这里交换的变量,a,和,b,的值,,point1,和,point2,,,p1,和,p2,的指向并没有变,还是指向原来的存储单元,但是,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,*p1,*p2);,10 ,11.2.2,使用指针变量,p1,存储数据,&a,point1,存储数据,&a,变量,a,1,p2,存储数据,&b,point2,存储数据,&b,变量,b,2,p2,存储数据,&a,point1,存储数据,&a,变量,a,1,p1,存储数据,&b,point2,存储数据,&b,变量,b,2,调用,swap,函数,把实参,point1,和,point2,传递给了形参,p1,和,p2,后,执行,swap,函数前:,交换函数执行后,调用并执行,swap,函数,,在,没有返回到主函数前:,11.2.3,指针的运算,针的运算就是地址的运算。由于这一特点,指针运算不同于普通变量,只允许有限的几种运算。除了可以对指针赋值外,指针的运算还包括移动指针、两个指针相减、指针与指针或指针与地址之间进行比较等。可以通过将指针加减一个整数,或者通过对指针赋值来移动指针。,例如:,p+n,、,p-n,、,p+,、,p-,、,+p,和,-p,等,其中,n,是整数。,将指针,p,加上或者减去一个整数,n,,表示,p,向地址增加或减小的方向移动,n,个元素单元,从而得到一个新的地址,使能访问新地址中的数据。每个数据单元的字节数取决于指针的数据类型。,11.2.3,指针的运算,如下图所示,变量,a,,,b,,,
展开阅读全文