第十章指针课题:第十章指针§1-§2教学目的:1、了解指针与地址的概念2、掌握指针变量的定义、初始化及指针的运算教学重点:教学难点:指针变量的定义、初始化及指针的运算指针的运算步骤一复习引导指针是C语言的一个重要概念,也是C语言的一个重要特色。正确而灵活地运用它,可以有效地表示复杂的数据结构;能动态分配内存;能方便地使用字符串;有效而方便地使用数组;在调用函数时能得到多于1个的值;能直接处理内存地址等,这对设计系统软件是很必要的。指针的概念比较复杂,使用也比较灵活,因此初学者时常会出错,务请在学习本章内容时十分小心。步骤二讲授新课§10.1地址和指针的概念计算机的主存储器被分成一个个存储单元,为了区分各存储单元,要为每个存储单元编号,这个编号即地址。例:i=3;或scanf(“%d”,&i);是将3送给i所在的空间。例:将3送到变量I_pointer所“指向”的单元(即I所标志的单元)。所谓“指向”,是通过地址来体现的,I_pointer中的值为2000,它是变量I的地址,这样就在I_pointer和变量之间建立起一种联系,即通过I_pointer能知道I的地址,从而找到变量I的内存单元。因而在C语言中,将地址形象化地称为“指针”。意思是通过它能找到以它为地址的内存单元。一个变量的地址称为该变量的“指针”。内存单元的地址和内存单元的内容是两个不同的概念。指针:就是地址,即内存单元的编号。指针变量:用来存放另一变量的地址(即指针)的变量。如:地址2000是变量i的指针;i_pointer是指针变量,其值就是指针2000。§10.2变量的指针和指向变量的指针变量变量的指针就是变量的地址。存放变量地址的变量是指针变量,用来指向另一个变量。*i_pointer表示i_pointer所指向的变量。一、定义一个指针变量指针变量的定义包含三个方面的内容:⑴指针类型说明,即定义变量为一个指针变量⑵指针变量名⑶变量值(指针)所指向的变量的数据类型。格式:存储类型基类型*指针变量名;例:int*pointer_1,*pointer_2;float*pointer_3;char*pointer_4;二、指针的引用指针变量有两个运算符:&:取地址运算符功能:取变量地址;单目,右结合。*:取内容运算符(“间接访问”运算符)功能:只能跟地址,取变量所指向单元的内容;单目,右结合。例:&a为变量a的地址,*p为指针变量p所指向的存储单元。例:inta=5,*p=&a;printf(“%d”,*p);main(){inta,b;int*pointer_1,*pointer_2;a=100;b=10;pointer_1=&a;/*把变量a的地址赋给pointer_1*/pointer_2=&b;/*把变量b的地址赋给pointer_2*/printf(“%d,%d\n”,a,b);printf(“%d,%d\n”,*pointer_1,*pointer_2);}输出结果:100,10100,10评注:1、在第3行虽然定义了两个指针变量,只是提供了两个指针变量,但并未指向任何一个整型变量。称为指针“悬空”。2、最后一行的*pointer_1和pointer_2就是变量a和b。3、程序中两处出现*pointer_1等,含义不同。程序第3行中的*pointer_1表示定义指针变量pointer_1。它前面的*只是表示该变量是指针变量。程序最后一行中的*pointer_1则代表变量,即pointer_1所指向的变量。4、第5行中的pointer_1=&a是将a的地址赋给指针变量pointer_1,而不是*pointer_1。注意:不应写成:*pointer_1=&a;5、从上例中可看出,*pointer_1等价于a,*pointer_2等价于b,故凡在程序中出现a的地方均可用*pointer_1代替。所以,若有:intx,y,*px=&x;则下面的运算均是正确的:y=*px+1;/*把x的内容加1送变量y*/printf(“%d\n”,px);/*打印当前x的内容*/d=sqrt((double)px);/*把x的平方根送变量d*/px=0;/*把x置为0*/*px+=1;/*把x的值加1*/(*px)++;/*使x的值加1*/y=(*px)++;/*即y=x,x++*/6、假设px和py都被定义为指向int对象的指针,而且px当前已指向了int型变量x,则执行:py=px;/*把指针px的内容拷贝到指针py中去*/即py和px这两个不同的指针指向了同一对象x7、指针不是整数,不能将它与整数混为一谈。例:#includestdio.hmain(){intx=100,*p;p=x;printf(“%d”,p);}例如:#includestdio.hmain(){inta,b,*d=&a;b=d;printf(“%d\n”,b);……}——编译不出错,但得不到希望的值关于&和*运算符的说明:假设已执行pointer_1=&a;1、&*pointer_1含义是什么?&*pointer_1与&a相同,即变量a的地址。2、*&a的含义是什么?先进行&a运算,得a的地址,再进行*运算。*&a、*pointer_1及变量a等价。3、(*pointer_1)++相当于a++。它与*pointer_1++不同。4、*pointer_1++等价于*(pointer_1++),即先进行*运算,得到a的值,然后使pointer_1的值改变,这样pointer_1不再指向a了。例10.2:输入a和b两个整数,按先大后小的顺序输出a和b。main(){int*p1,*p2,*p,a,b;scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;if(ab){p=p1;p1=p2;p2=p;}printf(“\na=%d,b=%d\n”,a,b);printf(“max=%d,min=%d\n”,*p1,*p2);}运行情况:5,9Entera=5,b=9max=9,min=5三、指针变量作为函数参数例10.3对输入的两个整数按大小顺序输出。先考察如下程序,看是否能得到预期的结果swap(intp1,intp2){inttemp;temp=p1;p1=p2;p2=temp;}main(){inta,b;scanf(“%d,%d”,&a,&b);if(ab)swap(a,b);printf(“\n%d,%d\n”,a,b);}不能得到预期的结果。改为:swap(int*p1,int*p2){inttemp;temp=*p1;*p1=*p2;*p2=temp;}main(){inta,b;int*pointer_1,*pointer_2;scanf(“%d,%d”,&a,&b);pointer_1=&a;pointer_2=&b;if(ab)swap(pointer_1,pointer_2);printf(“\n%d,%d\n”,a,b);}注:如果想通过函数调用得到n个改变的值,可以:1、在主调函数中设n个变量,用n个指针变量指向它们;2、然后将指针变量作实参,将这n个变量的地址传给所调用的函数的形参;3、通过形参指针变量,改变该n个变量的值;4、主调函数中就可以使用这些改变了值的变量。四、指针(变量)的初始化指针置初始化值的格式:存储类型基类型*指针名=初始化值;如:main(){staticinta;int*p=&a,*p1=p;……}再如:int*p=0;或int*p=NULL;五、指针的运算1、指针的算术运算指针仅能进行加、减算术运算如:p+n,p-n,p++,p--,++p,--pp-=n,p+=n,p1-p2等其中n是整数,p、p1、p2均为指针;施行加法运算时,指针向地址增大的方向移动;施行减法运算时,指针向地址减小的方向移动;移动长度取决于指针的基类型,由计算机决定;如有:inta,b,c,*pt=&a;则pt++则指针向后移动两个字节;再如:main(){int*p1,a=8,b=3;p1=&a;printf(“%d,%d\n”,(*p1)++,*p1++);printf(“%d,%d\n”,a,*p1);}运行结果:3,88,4注:p1+k=p1+k*sizeof(p1的基类型);p1-k=p1-k*sizeof(p1的基类型);如:strlen(char*s){char*p=s;while(*p!=‘\0’)p++;return(p-s);}2、指针的关系运算设指针p1,p2指向同一数组中的元素,则p1p2为真:表示p1在p2的前面;p1p2为假:表示p2在p1的前面;p1==p2:表示p1、p2指向数组中的同一元素;同理可推出、=、=、!=比较的意义;不可将指针与其他类型的对象作比较;若两指针指向不同数组中的元素,也不可比较;允许将指针与NULL或数值0进行==或!=的比较,以便判定一个指针是否为空指针。步骤三课堂小结本课介绍了指针与地址的概念,指针变量的定义、初始化及指针的运算。指针:就是地址,即内存单元的编号。指针变量:用来存放另一变量的地址(即指针)的变量。例如:inta=5,*p=&a;printf(“%d”,*p);注意:运算符*和&的用法,指针变量的自加自减运算。步骤四布置作业课后作业:第十章课后练习10.110.2课题:第十章指针§3教学目的:掌握指针与数组的知识教学重点:教学难点:指向数组的指针变量指向二维数组的指针步骤一复习引导上节课介绍了指针变量的定义及其赋值。一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组和数组元素(把数组起始地址或某一元素的地址放到一个指针变量中)。步骤二讲授新课所谓数组的指针是指数组的起始地址,数组元素的指针是数组元素的地址。引用数组元素可以用下标法(如a[3]),也可以用指针法,即通过指向数组元素的指针找到所需的元素。使用指针法能使目标程序质量高(占内存少,运行速度快)。一、指向一维数组的指针定义形式:inta[10];int*p;p=&a[0];或p=a;含义:把数组的首地址赋给指针变量p。也即:int*p=&a[0];或int*p=a;二、通过指针引用数组元素按C的规定:如果指针变量p已指向数组中的一个元素,则p+1指向同一个数组中的下一个元素(而不是简单地加1)。如果p的初值为&a[0],则:p+ia+i&a[i],即指向a数组的第i个元素。*(p+i)*(a+i)a[i]。指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价引用数组元素时,可以用:1、下标法,如:a[i]2、指针法,如:*(a+i)或*(p+i)其中,a是数组名,p是指向数组的指针例10.5:输出数组中的全部元素假设有一个a数组,整型,有10个元素。用三种方法输出各元素的值:1、下标法:main(){inta[10],i;for(i=0;i10;i++)scanf(“%d”,&a[i]);printf(“\n”);for(i=0;i10;i++)printf(“%d”,a[i]);}2、利用数组名计算数组元素地址,找出元素的值。main(){inta[10],i;for(i=0;i10;i++)scanf(“%d”,&a[i]);printf(“\n”);for(i=0;i10;i++)printf(“%d”,*(a+i));}3、用指针变量指向数组元素。main(){inta[10],*p,i;for(i=0;i10;i++)scanf(“%d”,&a[i]);printf(“\n”);for(p=a;p(a+10);p++)printf(“%d”,*p);}评注:1、第1和2种方法执行效率是相同的。2、第3种方法效率高。3、用下标法比较直观。在使用指针变量时,有几个问题要注意:1、指针变量可以实现使本身的值改变。如:for(p=a;p(a+10);p++)2、要注意指针变量的当前值