课程-15级语言第6章指针_第1页
课程-15级语言第6章指针_第2页
课程-15级语言第6章指针_第3页
课程-15级语言第6章指针_第4页
课程-15级语言第6章指针_第5页
免费预览已结束,剩余60页可下载查看

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1--存储单元地址的使用第6章指针2教学目标理解指针和指针变量的基本含义掌握指针的声明和存放,初始化和指针变量的引用方法掌握指针作为函数的参数了解指向数组的指针掌握指向字符串的指针能在程序运行时应用动态分配预留新的存储空间基本数据类型回顾数据类型:数据类型是对外界信息的抽象表示,便于计算机处理3数组浮点型整型字符型指针引入4除了上述值型数据,C语言还能处理一类非常特殊的数据—内存地址。计算机内部有很多存储单元,每个存储单元都用唯一的地址编号(表示为一个整数加以相互区别),简称为地址。在C语言中,存储地址也叫指针6.1指针与指针变量在C语言中,指针的重要特征:数据结构总是位于计算机的内存中,必有地址,即指针使用指针可以节约大量内存空间指针使程序的不同部分能共享数据,在数组作为函数的参数中已经有所理解。程序能在运行时能够动态地管理内存空间,指针显得更为方便56.1指针与指针变量在C语言中,任何一个指向能存储数据的内存位置的表达式称为左值(lvalue)x=1.0;x

6变量的名称1.0变量的存储单元2000变量的指针变量的值76.1指针与指针变量整型指针的存储整型变量的存储6.2指针变量的定义与引用

6.2.1指针变量的定义变量须先定义后使用使用指针变量前,必须先对它们进行声明。指针变量的声明语法:基本数据类型说明符*标识符名称;(a)int指针变量(b)float指针变量(c)char指针变量如:int*ptr1;float*ptr2;char*ptr3;6.2.1指针变量的定义9说明:(1)定义指针变量时名称前加*号。如:

char*ptrc,c;(2)声明中出现的*不是运算符,它只是表明被声明的变量是指针变量。(3)指针变量可以被声明为指向任何数据类型的变量。6.2.2指针变量的引用指针变量的使用方法同普通变量一致,都可以进行赋值和取值操作10int*p1,m=3;float*p2,f=4.5;char*p3,ch='a';int*intPtr;p1=&m;p2=&f;p3=&ch;intPtr=p1;运算符&的含义是取出变量m在内存中的存储指针6.2.2指针变量的引用11指针变量可以指向任何与之相一致的数据类型的变量,没有赋值时,指针变量的值是不确定的,从而不能确定它具体的指向,只有为其赋值,指针变量才有意义对指针变量的引用形式为:*指针变量其含义是取出指针变量所指向内存单元中的值

6.2.2指针变量的引用[例6.1]用指针变量进行输入、输出。intmain(){int*p,m;scanf("%d",&m);/*&:取变量m的指针*/p=&m; /*指针p指向变量m*/printf("%d",*p);/**p是对指针所指的变量的引

用形式,与m意义相同*/printf("%x",p);/*输出指针变量p中的指针,指

针是以整数形式表示的*/return0;}

6.2.2指针变量的引用13指针变量可以在声明时或在赋值语句中初始化。指针可以被初始化为0、NULL或普通变量的地址.如:intm=3;int*ptr=&m;double*dblPtr=0;int*strPtr=NULL;符号常量NULL在头文件<stdio.h>中定义,表示数值0。把一个指针初始化为NULL和0是等价的用普通整型变量m的指针初始化变量dblPtr指针变量不指向任何浮点数,空指针strPtr指针变量不指向任何整型数,空指针6.2.2指针变量的引用14说明:尽可能使用初始化操作来初始化指针变量,以防止其指向一个未知的或未被初始化的内存空间6.3指针运算符与指针表达式6.3.1指针运算符与指针表达式&运算符

取址运算符&m变量m的地址*运算符

间接访问运算符*ptr所指向的变量取址运算符及表达式15变量的定义类型&运算符表达式含义charch;char&ch取出变量ch的指针doublex;double&x取出变量x的指针inti;int&i取出变量i的指针inta[10];int&a[1]取出数组元素a[1]的指针charstr[10];char&str取出数组元素str[0]的指针6.3.1指针运算符与指针表达式间接访问运算符及表达式16变量的定义含义char*ptrch,ch;ptrch=&ch;printf("%c",*ptrch);定义指向char的指针变量ptrch和char变量ch取出变量ch的指针赋值给指针变量ptrch以字符方式输出间接访问ptrch所指向的指针中的值double*ptrx,x;ptrx=&x;printf("%lf",*ptrx);定义指向double的指针变量ptrx和double变量x取出变量x的指针赋值给指针变量ptrx以浮点数方式输出间接访问ptrx所指向的指针中的值int*ptri,i;ptri=&I;printf("%d",*ptri);定义指向int的指针变量ptri和int变量i取出变量i的指针赋值给指针变量ptri以整型方式输出间接访问ptri所指向的指针中的值6.3.1指针运算符与指针表达式说明:*号在C语言中有三种含义,表示算术运算中的乘法在变量声明中指针变量的修饰符在表达式中的单目运算符存储单元中的值的访问方式有两种。通过变量名称访问,比如:inta[10],i=1;printf("%d”,a[i]);

通过指针间接访问单元的值17#include<stdio.h>

intmain(){

int*ptra,*ptrb,a,b,t;/*定义指针变量与整型变量*/

scanf("%d,%d",&a,&b);

ptra=&a;/*使指针变量指向整型变量*/

ptrb=&b;

if(*ptra<*ptrb){/*通过间接访问形式交换两个单元的值*/

t=*ptra;*ptra=*ptrb;*ptrb=t;

}

printf("a=%d,b=%d\n",a,b);

printf("*ptra=%d,*ptrb%d\n",*ptra,*ptrb);

return0;

}[例6.2]从键盘输入两个整数,用间接访问的形式由大到小的输出这两个数186.3.1指针运算符与指针表达式程序运行过程中,指针与所指的变量之间的关系196.3.1指针运算符与指针表达式[例6.3]从键盘上输入两个整数,按从大到小的顺序输出两个整数的值。20#include<stdio.h>intmain(){int*ptra,*ptrb,a,b,*t;/*定义指针变量与整型变量*/scanf("%d,%d",&a,&b);ptra=&a;/*使指针变量指向整型变量*/ptrb=&b;if(*ptra<*ptrb){/*间接访问交换两个单元的值*/

t=ptra;ptra=ptrb;ptrb=t;}printf("%d,%d\n",a,b);printf("%d,%d\n",*ptra,*ptrb);return0;}

6.3.2指针变量作函数的参数指针变量作函数的参数的实质:

地址传递核心特点:

共享内存21考虑下列代码,能实现参数值的互换吗?voidswap0(intx,inty){intt=x;x=y;y=t;return;}不能,如何做才能将参数的值交换?6.3.2指针变量作函数的参数[例6.4]利用指针变量作为函数的参数,设计函数swap实现两个整数的交换。22#include<stdio.h>voidswap1(int*,int*);/*函数声明,形参为指针型数据*/intmain(){ int*p1,*p2,a,b; scanf("%d,%d",&a,&b); p1=&a; p2=&b; swap(p1,p2);/*函数调用,实参为指针变量*/ printf("%d,%d\n",a,b); printf("%d,%d\n",*p1,*p2); return0;}/*实现将两数值调整为由大到小*/voidswap1(int*pt1,int*pt2){intt;/*交换内存变量的值*/if(*pt1<*pt2){t=*pt1;*pt1=*pt2;*pt2=t;}}/*实现将两数值调整为由大到小*/voidswap2(int*pt1,int*pt2){ int*t;//交换 if(*pt1<*pt2){

t=pt1; pt1=pt2; pt2=t;

}}6.3.3返回指针的函数函数可以返回整型、实型、字符型等类型的数据,还可以返回地址值-即返回指针值。返回指针值的函数定义:类型名*函数名(参数表);

例如:

int*fun(intx,inty);

表示fun是返回整型指针的函数,返回的指针值指向一个整型数据。236.3.3返回指针的函数[例6.5]返回两个数中大数地址的函数。#include<stdio.h>int*fun(int,int);intmain(){inti,j,*p;printf("entertwonumtoi,j:");scanf("%d%d",&i,&j);p=fun(i,j);/*调用fun,返回大数地址,赋值给指针变量p*/printf("max=%d\n",*p);/*打印p指向的数据*/return0;}24/*fun函数返回形参x,y中较大数的指针

*/int*fun(intx,inty){int*z;if(x>y)z=&x;elsez=&y;returnz;}程序运行结果:输入:entertwonumtoi,j:218输出:max=186.4指针与数组对数组来说,数组名就是数组在内存存储区域范围的首地址,即是一个指针,只不过这个指针是一个常量。指针变量可以用于存储变量的地址,当然也可存放数组的指针或数组元素的指针对数组而言,数组和数组元素的引用,也可以通过使用指针的方式进行间接访问256.4.1指针与一维数组26例intarray[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]p6.4.1指针与一维数组指针间接访问数组元素:ptr+n与a+n表示数组元素a[n]的地址,即&a[n]。对整个a数组来说,共有10个元素,n的取值为0~9,则数组元素的地址就可以表示为ptr+0~ptr+9或a+0~a+9,与&a[0]~&a[9]保持一致。间接访问*(ptr+n)和*(a+n)就表示为数组的各元素即等效于a[n]。指向数组的指针变量也可用数组的下标形式表示为ptr[n],其效果相当于*(ptr+n)27inta[10],*ptr; /*声明数组与指针变量*/ptr=a;/*或者:ptr=&a[0];称为ptr指向数组a*/6.4.1指针与一维数组例6.6以数组的不同引用形式输入输出数组各元素#include<stdio.h>intmain(){ inti,a[10]; for(i=0;i<=9;i++) scanf("%d",a+i); printf("\n"); for(i=0;i<=9;i++) printf("%4d",a[i]); printf("\n"); return0;}28程序运行结果:输入:12345678910输出:12345678910#include<stdio.h>intmain(){inti,a[10],*ptr=a;for(i=0;i<=9;i++)scanf("%d",ptr+i);printf("\n");for(i=0;i<=9;i++)printf("%4d",*(ptr+i));printf("\n");return0;}#include<stdio.h>intmain(){inti,a[10];for(i=0;i<=9;i++)scanf("%d",a+i);printf("\n");for(i=0;i<=9;i++)printf("%4d",*(a+i));printf("\n");return0;}#include<stdio.h>intmain(){inti,a[10],*ptr=a;for(i=0;i<=9;i++) scanf(“%d”,&ptr[i]);printf(“\n”);for(i=0;i<=9;i++) printf(“%4d”,ptr[i]);printf(“\n”);return0;}#include<stdio.h>intmain(){inti,a[10],*ptr=a;for(i=0;i<=9;i++) scanf(“%d”,ptr++);printf("\n");ptr=a;for(i=0;i<=9;i++) printf(“%4d”,*ptr++));printf(“\n”);return0;}#include<stdio.h>intmain(){inti,a[10],*ptr=a;for(i=0;i<=9;i++) scanf(“%d”,ptr++);printf(“\n”);for(i=0;i<=9;i++) printf(“%4d”,*ptr++);printf(“\n”);return0;}合适吗?ptr=a;6.4.2指针与二维数组若定义一个二维数组:inta[3][4];29a[0]a[0][0]a[0][1]a[0][2]a[0][3]a[1]a[1][0]a[1][1]a[1][2]a[1][3]a[2]a[2][0]a[2][1]a[2][2]a[2][3]行地址数组元素6.4.2指针与二维数组二维数组在内存中的存放和指针与二维数组的关系30a[0]4062196a[0][0]4062200a[0][1]4062204a[0][2]4062208a[0][3]4062212a[1][0]4062216a[1][1]4062220a[1][2]4062224a[1][3]4062228a[2][0]4062232a[2][1]4062236a[2][2]4062240a[2][3]a[1]a[2]二维数组元素表示形式:(1)a[1][2](2)*(a[1]+2)(3)*(*(a+1)+2)(4)*(&a[0][0]+1*4+2)地址表示:(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+231表示形式含义地址a二维数组名,数组首地址,指向一维数组a[0],即第0行首地址a[0],*(a+0),*a第0行第0列元素地址a+1,&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列元素值40621964062196406221240622124062220元素值为56.4.2指针与二维数组例6.10用地址法输入输出二维数组各元素32#include<stdio.h>intmain(){inta[3][4];inti,j;for(i=0;i<3;i++)for(j=0;j<4;j++) scanf("%d",a[i]+j);for(i=0;i<3;i++){for(j=0;j<4;j++) printf("%4d",*(a[i]+j)); printf("\n");}return0;}

#include<stdio.h>intmain(){inta[3][4];inti,j;for(i=0;i<3;i++)for(j=0;j<4;j++)scanf("%d",a[i]+j);for(i=0;i<3;i++){for(j=0;j<4;j++)printf("%4d",*(a[i]+j));printf("\n");}return0;}

6.4.3数组指针作函数的参数例6.12编写函数,利用指针参数实现求解一维数组中的最大元素intmax(intx[],intn){ intmaxv=x[0]; inti; for(i=1;i<n;i++) if(maxv<x[i]) maxv=x[i]; returnmaxv;}33测试程序的main()函数中调用部分如下:ptr=a;maxvalue=max(ptr,10);6.4.3数组指针作函数的参数实

参形

参数组名数组名数组名指针变量指针变量数组名指针变量指针变量346.4.3数组指针作函数的参数例6.14将一个班级中若干名同学的不同课程的成绩累计求和,输出同学的成绩和与总分大于均分的同学分析:选用二维数组作为学生成绩的存储结构,每个同学的成绩就是二维数组中的一行,每一列表示同学的某门课程的成绩。在实现时,我们用二维数组的指针作函数的参数,实现对二维数组的按行相加,当然还可以另外定义一个存储学生的信息。此处,我们只描述学生的成绩信息。356.4.4指针与字符数组C语言允许使用两种方法实现一个字符串的引用。字符数组字符串366.4.4指针与字符数组例6.15简单字符串的输入和输出#include<stdio.h>intmain(){ charstr[80]; gets(str); printf("%s\n",str); return0;}376.4.4指针与字符数组字符类型指针指向字符串,其定义的方法为:

charstr[80],*p;*p=str;例6-16字符数组的正确使用方法。38#include<stdio.h>intmain(){charstr[10],*p=str;inti;/*输入的字符串长度超过10*/scanf("%s",str);for(i=0;i<10;i++)printf("%c",*p++);/*正确输出*/printf("\n");p=str;/*字符数组无'\0'标志,输出出错*/printf("%s",p); /*字符数组无'\0'标志,输出出错*/puts(str); return0;}6.4.4指针与字符数组例6-17实现两个字符串的复制、合并操作39voidstrcopy(char*s,constchar*t){while((*s=*t)!='\0'){ s++;t++;}}voidstrcat(char*s,char*t){/*移动串s到串尾*/while(*s)s++;/*将串t接在串s后,实现串的连接*/

while(*t)*s++=*t++;/*在串结尾处写入结束符*/*s='\0';}

串复制时,串s的长度应大于等于串t;串连接时,串s的长度应大于等于串s与串t的长度之和。以免出现存储的溢出。6.4.4指针与字符数组字符数组和字符(串)指针的区别存储上的区别:字符数组元素存放一个字符,

字符指针存放是地址2

赋值上的区别:对字符数组只能对各个元素赋值(字符数组定义例外)。可以将一个常量字符串赋值给字符指针,含义是将常量串首地址赋值给字符指针。如:charstr[100];str=”Iamastudent.”;//非法char*pstr;pstr=”Iamastudent.”;//合法406.4.4指针与字符数组3定义上的区别:定义数组后,编译系统分配具体的内存单元。定义指针变量,编译系统只分配一个存储单元,以存放地址值,这个值是随机的,所以字符指针必须初始化才能使用。char*s[10];gets(s);//合法char*ps;get(ps);/*指针没有一个确切的指向,非法*/运算上的区别:指针变量的值允许改变(++,--,赋值等),而字符数组的数组名是常量地址,不允许改变。416.4.4指针与字符数组例6-18字符串数组的排序,使用指向二维数组的指针字符串排序主要依据字符串的字典顺序排序42分析:我们定义一个字符串数组来存放多个字符串,每个字符串由两部份构成,如果第一部分一致,再根据第二部分排序,排序依据为字符串的字典顺序。6.5指针的地址分配当定义指针变量时,其变量的取值是随机的,可能指向内存的任一单元。若指针的指向是不安全的内存地址,在该地址空间上的数据交换就会产生意料不到的效果.43在程序执行时为指针变量所做的地址分配就称之为动态内存分配6.5指针的地址分配ANSIC标准建议使用两个最常用的动态分配内存的函数malloc()和free().包含在stdlib.h中函数原型为:void*malloc(size_tsize);voidfree(void*ptr);

malloc()用以向编译系统申请分配内存;

free()用以在使用完毕释放掉所占内存。446.5指针的地址分配例6-19两个字符串的交换45#include<string.h>#include<stdio.h>intmain(){ char*ptr1,*ptr2,*temp; ptr1=(char*)malloc(30);/*动态为指针变量分配长度为30字节的存储空间*/ ptr2=(char*)malloc(20); temp=(char*)malloc(30); printf("inputstr1:"); gets(ptr1);/*输入字符串*/ printf("inputstr2"); gets(ptr2);6.5指针的地址分配46printf("str1------------str2\n"); printf("%s.......%s\n",ptr1,ptr2);

strcpy(temp,ptr1);/*串复制*/ strcpy(ptr1,ptr2); strcpy(ptr2,temp); printf("str1------------str2\n"); printf("%s.......%s\n",ptr1,ptr2);

free(ptr1); free(ptr2);free(temp); return0;}

例6-19续程序运行结果:输入:inputstr1:Helloinputstr2:world输出:str1------------str2Hello.......worldstr1------------str2world.......Hello6.6指针数组一种特殊的数组,数组元素全部是指针,以替代变量本身在程序中的使用,增加灵活性。称这类数组为指针数组。定义形式:类型标识*数组名[数组长度];如:char*str[4];int*ptr[5];47整型数组,数组元素为整型数指针数组,数组元素为指针运算符[]的优先级比运算符*高先是数组形式str[4],然后才是与“*”的结合,表示数组中有四个元素,每个元素都是一个指向字符数据的指针6.6指针数组说明:(1)指针数组是数组元素都为指针的数组,数组的指针,指的是数组的首地址。(2)注意与指向二维数组的行指针的区别。行指针声明形式为:int(*ptr)[4],a[3][4],b[3][3];

说明指针变量ptr只能指向一个长度为4数组;ptr=a[0];//合法ptr=b[0];/*非法,数组b的行指针是一个长度

为3的一位数组*/48数组指针的定义为形式为:int*pt[4];6.6指针数组指针数组用的最多的是“字符型指针数组”,利用字符指针数组可以指向多个长度不等的字符串,使字符串处理更加方便、灵活,节省内存空间,如图496.6指针数组使用字符型指针数组指向多个字符串与使用两维字符数组存储多个字符串的比较:节省存储空间(二维数组要按最长的串开辟存储空间)便于对多个字符串进行处理,节省处理时间(使用指针数组排序各个串不必移动字符数据,只要改变指针指向的地址)506.6指针数组#include<string.h>#include<stdio.h>voidsort(char*name[],intn);intmain(){

char*CourseName[]={"CProgram","C++ObjectOrientedProgram“,"OperatingSystem","DataSturctureandAlgorithms" }; inti,n=4; sort(CourseName,n); for(i=0;i<n;i++) printf("%s\n",CourseName[i]); system("Pause"); return0;}51voidsort(char*name[],intn){/*选择法排序*/char*temp;inti,j,k;for(i=0;i<n-1;i++){ k=i; for(j=i+1;j<n;j++) if(strcmp(name[j],name[k])<0)k=j; if(k!=i){ temp=name[i];name[i]=name[k];name[k]=temp; }}}字符串数组排序6.6指针数组若定义一个指针数组,对各元素的取值要注意安全性。

如:char*ptr[3];若:

scanf("%s",ptr[i]);则输入的字符串在内存的存放其地址由ptr[i]决定除非给指针数组元素赋值安全的地址。52包含三个指针,但指针的指向是不确定的,指针现在可能指向内存的任一地址若ptr[i]没有指向一个有效的地址,非法6.6指针数组例6.21对已排好序的字符指针数组进行指定字符串的查找,符串按字典顺序排列,采用二分法或折半查找53分析:折半查找算法描述:(1)输入n个字符串,分别由指针数组的元素指向。按照字典顺序排序,我们选用上例中的sort函数实现。(2)设low指向指针数组的低端,high指向指针数组的高端,mid=(low+high)/2(3)测试mid所指的字符串,是否为要找的字符串。(4)若按字典顺序,mid所指的字符串大于要查找的串,表示被查字符串在low和mid之间,否则,表示被查字符串在mid和high之间。(5)修改low式high的值,重新计算mid,继续寻找。

6.7指向指针的指针指针可以指向简单变量、字符类型变量,当然也可以指向指针类型变量。当指向指针类型变量时,称之为指向指针的指针变量,这是指针也称为双重指针。

定义:

类型标识符**指针变量名;

546.7指向指针的指针如:float**ptr;由于指针运算符“*”是自右至左结合,所以上述定义相当于:

float*(*ptr);例6-22利用指向指针的指针变量对二维字符数组的访问55定义一个指针变量ptr,它指向另一个指针变量(该指针变量又指向一个实型变量)#include<stdio.h>intmain(){ inti; staticcharc[][30]={"CProgram","DataStructure", "OperatingSystem","DataBaseSystem"}; staticchar*cp[]={c[0],c[1],c[2],c[3]};/*指针数组*/

staticchar**cpp;/*指向字符指针的指针变量*/

cpp=cp;/*将指针数组的首地址传递给指向字符指针的指针变量*/ for(i=0;i<4;i++)/*按行输出字符串*/ printf("%s\n",*cpp++); printf("-----------\n"); for(i=0;i<4;i++){/*按行输出字符串*/

cpp=&cp[i]; printf("%s\n",*cpp); } return0;}566.8指向函数的指针变量C语言规定函数的首地址即函数名,所以函数名就是函数的指针。指向函数的指针变量就是保存函数入口地址(函数指针)的变量,称这种变量为指向函数的指针变量。定义:

类型(*函数指针变量名)();例如:int(*p)();57两组括号()都不能少int表示被指向的函数的类型,即被指向的函数的返回值的类型6.8指向函数的指针变量使用方法有两种:指向函数的指针变量的赋值,指向某个函数:

函数指针变量名=函数名;利用指向函数的指针变量调用函数:(*函数指针变量名)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论