数据结构第一章c语言指针_第1页
数据结构第一章c语言指针_第2页
数据结构第一章c语言指针_第3页
数据结构第一章c语言指针_第4页
数据结构第一章c语言指针_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

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

文档简介

C语言指针专题Copyright2008ByNeusoftGroup.Allrightsreserved变量变量类型局部变量全局变量静态变量请问下面代码中,哪些是局部变量?哪些是全局变量?哪些是静态变量?

intpi=3;

intArea(intr,int*sum) { intb; staticintc=0; b=pi*r*r; c+=b; *sum=c; returnb; }内存内存类型内存分为静态内存和动态内存,动态内存又可以分为堆内存和栈内存。内存分配方式相应的分为静态存储区域分配、栈创建、堆分配。静态存储区域分配程序在编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如前面例子中的全局变量(intpi)、静态变量(staticintc)和常量;栈创建函数执行的时候,函数内的局部变量(包括函数参数)的存储单元都是在栈上创建的,函数执行后占用栈的存储单元会自动被释放。这种分配效率很高,但是分配的内存容量有限。占用栈内存多了,会出现栈溢出;例如函数area的参数(intr,int*sum)和局部变量(intb)就是栈创建的。堆分配也称动态存储分配,是指程序在运行时候用malloc申请的内存,程序员自己负责在何时用free释放内存。这种分配虽然灵活,但是使用时容易出错,需要注意。内存分为4个区域:栈区auto静态区static堆区heap代码区code数据区代码区memory存放程序的代码存放程序的全局数据和静态数据存放程序动态申请的数据存放程序的局部数据和参数申请大小的限制①Stack:栈是向低地址扩展的数据结构,是一块连续的内存的区域。栈顶的地址和栈的最大容量是系统预先规定好的。②Heap:堆是向高地址扩展的数据结构,是不连续的内存区域。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。内存1指针的概念变量与地址程序中:inti;

floatk;

内存中每个字节有一个编号-----地址…...…...200020042008内存0ik

编译或函数调用时为其分配内存单元变量是对程序中数据存储空间的抽象…...…...200020042008整型变量i10变量i_pointer指针与指针变量指针:一个变量的地址指针变量:专门存放变量地址的变量2000指针指针变量

变量的内容

变量的地址i_pointer200010i变量i地址是2000,指针变量i_pointer地址是2004直接访问与间接访问直接访问:按变量地址存取变量值间接访问:通过存放变量地址的变量去访问变量例

i=3;-----直接访问指针变量…...…...20002008整型变量i10变量i_pointer200420003例*i_pointer=20;-----间接访问20指针变量…...…...20002008200C整型变量i10变量i_pointer20042000整型变量k例

k=i;--直接访问

k=*i_pointer;--间接访问10例

k=i;k=*i_pointer;2指针变量:指针变量与其所指向的变量之间的关系指针变量的定义一般形式:[存储类型]

数据类型*指针名;3变量i2000i_pointer*i_pointeri*i_pointer&ii_pointeri=3;*i_pointer=33变量i2000i_pointer*i_pointeri*i_pointer&ii_pointeri=3;*i_pointer=3合法标识符指针变量本身的存储类型指针的目标变量的数据类型表示定义指针变量不是‘*’运算符例int

*p1,*p2;float*q;staticchar*name;注意:1、int*p1,*p2;

与int*p1,p2;2、指针变量名是p1,p2,不是*p1,*p23、指针变量只能指向定义时所规定类型的变量4、指针变量定义后,变量值不确定,应用前必须先赋值指针变量的初始化一般形式:[存储类型]

数据类型*指针名=初始地址值;赋给指针变量例inti,j;

int*pointer_1,*pointer_2;pointer_1=&i;pointer_2=&j;一个指针变量只能指向同一个类型的变量例

inti,j;

float*pointer;pointer=&i;例floati,j;

float*pointer_1,*pointer_2;pointer_1=&i;pointer_2=&j;例:通过指针变量访问整型变量#include<stdio.h>voidmain(){inta,b;int*pointer_1,*pointer_2;a=100;b=10;pointer_1=&a;pointer_2=&b;printf("%d,%d",a,b);printf("%d,%d",*pointer_1,*pointer_2);}运行结果;100,10100,10运行结果:a=5,b=9max=9,min=5例输入两个数,并使其从大到小输出#include<stdio.h>voidmain(){int*p1,*p2,*p,a,b;scanf("%d,%d",&a,&b);p1=&a;p2=&b;if(a<b){p=p1;p1=p2;p2=p;}printf("a=%d,b=%d\n",a,b);printf("max=%d,min=%d\n",*p1,*p2);}方法:交换指针变量的值零指针与空类型指针零指针:(空指针)定义:指针变量值为零表示:int*p=0;

p指向地址为0的单元,系统保证该单元不作它用表示指针变量值没有意义#defineNULL0int*p=NULL:p=NULL与未对p赋值不同用途:避免指针变量的非法引用在程序中常作为状态比较

例int*p;......while(p!=NULL){...…}void*类型指针表示:void*p;使用时要进行强制类型转换例char*p1;void*p2;p1=(char*)p2;p2=(void*)p1;表示不指定p是指向哪一种类型数据的指针变量指针变量作为函数参数——地址传递特点:共享内存,“双向”传递voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}voidmain(){inta,b;scanf("%d,%d",&a,&b);if(a<b)swap(a,b);printf("\n%d,%d\n",a,b);}例

调用子函数,将数从大到小输出…...…...20002010201420042008200C5变量a

变量b(main)9

变量temp

变量y

变量x(swap)55959COPY指针变量作为函数参数——地址传递特点:共享内存,“双向”传递swap(intx,inty){inttemp;temp=x;x=y;y=temp;}main(){inta,b;scanf("%d,%d",&a,&b);if(a<b)swap(a,b);printf("\n%d,%d\n",a,b);}例调用子函数,将数从大到小输出值传递…...…...20002010201420042008200C5变量a

变量b(main)9运行结果:5,9voidswap(intx,inty){intt;t=x;x=y;y=t;}voidmain(){inta,b;int*pointer_1,*pointer_2;scanf("%d,%d",&a,&b);

pointer_1=&a;pointer_2=&b;if(a<b)

swap(*pointer_1,*pointer_2);printf("\n%d,%d\n",a,b);}例调用子函数,将数从大到小输出…...20002010201420042008200C2018201C2020...59整型a

整型b(main)pointer_1pointer_2200020049COPY(swap)整型x整型y整型t5559voidswap(intx,inty){intt;t=x;x=y;y=t;}voidmain(){inta,b;int*pointer_1,*pointer_2;scanf("%d,%d",&a,&b);

pointer_1=&a;pointer_2=&b;if(a<b)

swap(*pointer_1,*pointer_2);printf("\n%d,%d\n",a,b);}例调用子函数,将数从大到小输出值传递…...…...20002010201420042008200C59运行结果:5,9整型a

整型b(main)pointer_1pointer_220002004voidswap(int*p1,int*p2){intp;p=*p1;*p1=*p2;*p2=p;}voidmain(){inta,b;int*pointer_1,*pointer_2;scanf("%d,%d",&a,&b);

pointer_1=&a;pointer_2=&b;if(a<b)swap(pointer_1,pointer_2);printf("\n%d,%d\n",a,b);}…...20002010201420042008200C2018201C2020...59整型变量a

整型变量b(main)指针pointer_1指针pointer_220002004(swap)指针p1指针p2整型p5920002004COPY5例调用子函数,将数从大到小输出swap(int*p1,int*p2){intp;p=*p1;*p1=*p2;*p2=p;}main(){inta,b;int*pointer_1,*pointer_2;scanf("%d,%d",&a,&b);pointer_1=&a;pointer_2=&b;if(a<b)swap(pointer_1,pointer_2);printf("\n%d,%d\n",a,b);}…...20002010201420042008200C2018201C2020...59整型变量a

整型变量b(main)指针pointer_1指针pointer_22000200459例调用子函数,将数从大到小输出运行结果:9,5地址传递方法:交换整型变量的值3

指针与数组指向数组元素的指针变量定义inta[10];int*p;赋值p=&a[0];

等价于

p=a;2000a[0]2004a[1]2008a[2]200ca[3]2010a[9]...整型指针p2000p数组名是表示数组首地址的地址常量p=a的作用是把数组的首地址赋给指针变量P,而不是把数组a的各元素赋给p。

也可,在定义指针变量时赋初值

int*p=a;数组元素表示方法a[0]a[1]a[2]a[3]a[9]...aa+9a+1a+2地址元素下标法a[0]a[1]a[2]a[9]a[0]a[1]a[2]a[3]a[9]...pp+9p+1p+2地址元素指针法*p*(p+1)*(p+2)*(p+9)[]变址运算符a[i]

*(a+i)a[i]p[i]*(p+i)*(a+i)*a*(a+1)*(a+2)*(a+9)p[0]p[1]p[2]p[9]例输出数组中的全部元素(3种方法)voidmain(){inta[10]inti;for(i=0;i<10;i++) scanf("%d",&a[i]);printf("\n");for(i=0;i<10;i++) printf("%d",a[i]);}(1)下标法voidmain(){inta[10]inti;for(i=0;i<10;i++) scanf("%d",&a[i]);printf("\n");for(i=0;i<10;i++) printf("%d",*(a+i));}(2)数组名计算数组元素的地址voidmain(){inta[10];int*p,i;for(i=0;i<10;i++) scanf("%d",&a[i]);printf("\n");for(p=a;p<(a+10);p++) printf("%d",*p);}(3)指针变量法指针变量的运算p++,使p指向下一元素a[1];*p++,++和*同优先级,自右至左,等价于*(p++)*(p++)和*(++p)作用不同。前者,先取*p值,再使p+1。后者先使p+1,再取*p。++和--运算符可以使指针变量向前或向后移动。若p1与p2指向同一数组,p1-p2=两指针间元素个数(p1-p2)/d例voidmain(){inta[]={5,8,7,6,2,7,3};inty,*p=&a[1];y=(*--p)++;printf("%d",y);printf("%d",a[0]);}输出:56pp58762730123456a例注意指针变量的运算6数组名作函数参数main(){intarray[10];……f(array,10);……}f(intarr[],intn){……}array实参数组名,代表该数组首元素的地址arr形参数组名,用来接收从实参传递过来的数组首元素的地址,实际上,形参数组名是按指针变量处理的f(int*arr,intn){……}*(arr+i)和arr[i]等价形参数组和实参数组共占同一段内存单元,在函数调用期间,如果改变了形参数组的值,在主调函数中可以使用这些已改变的值。数组中形参和实参对应关系实参形参数组名指针变量数组名指针变量数组名数组名指针变量指针变量序号1234main(){inta[10];

f(a,10);}f(intx[],intn){……}main(){inta[10];

f(a,10);

}f(int*x,intn){……}main(){inta[10],*p;p=a;

f(p,10);}f(int*x,intn){……}main(){inta[10],*p;p=a;

f(p,10);}f(intx[],intn){……}例将数组a中的n个整数按相反顺序存放实参与形参均用数组名voidinv(intx[],intn){intt,i,j,m=(n-1)/2;for(i=0;i<=m;i++){j=n-1-i; t=x[i];x[i]=x[j];x[j]=t;}}voidmain(){inti,a[10]={3,7,9,11,0,6,7,5,4,2};inv(a,10);printf("Thearrayhasbeenreverted:\n");for(i=0;i<10;i++)printf("%d,",a[i]);printf("\n");}a[0]和a[n-1]对换a[1]和a[n-2]对换a[int((n-1)/2)]和

a[n-int((n-1)/2)-1]对换a[0]a[8]a[1]a[7]奇数n=9a[4]a[4]ij379110675420123456789ijijijji11760594723m=4偶数n=10a[0]a[9]a[1]a[8]a[4]a[5]例将数组a中的n个整数按相反顺序存放voidinv(int*x,intn){intt,*p,*i,*j,m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i<=p;i++,j--){t=*i;*i=*j;*j=t;}}voidmain(){inti,a[10]={3,7,9,11,0,6,7,5,4,2};inv(a,10);printf("Thearrayhasbeenreverted:\n");for(i=0;i<10;i++)printf("%d,",a[i]);printf("\n");}实参用数组名,形参用指针变量37911067542a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]xp=x+ma数组60711594723ijijijjiji例将数组a中的n个整数按相反顺序存放voidinv(int*x,intn){intt,*i,*j,*p,m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i<=p;i++,j--){t=*i;*i=*j;*j=t;}}voidmain(){inti,a[10],*p=a;for(i=0;i<10;i++,p++)scanf("%d",p);

p=a;

inv(p,10);printf("Thearrayhasbeenreverted:\n");for(p=a;p<a+10;p++)printf("%d",*p);}实参与形参均用指针变量例将数组a中的n个整数按相反顺序存放voidinv(intx[],intn){intt,i,j,m=(n-1)/2;for(i=0;i<=m;i++){j=n-1-i;t=x[i];x[i]=x[j];x[j]=t;}}voidmain(){inti,a[10],*p=a;for(i=0;i<10;i++,p++)scanf("%d",p);

p=a;

inv(p,10);printf("Thearrayhasbeenreverted:\n");for(p=arr;p<arr+10;p++)printf("%d",*p);}实参用指针变量,形参用数组名多维数组与指针多维数组的地址a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]1357911131517192123a[0]a[1]a[2]===a定义二维数组:inta[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};二维数组a是由三个一维数组组成的。a数组包含三个元素:a[0],a[1],a[2]。每个元素又是一个一维数组包含四个元素。a[0],a[1],a[2]是一维数组名,数组名代表数组的首地址,a[0]=&a[0][0],a[1]=&a[1][0],a[2]=&a[2][0]。200012004320085200C720109201411201813201C15202017202419202821203023aa+1a+2a[0]+0a[0]+1a[0]+2a[0]+3a[i]和*(a+i)等价,所以a[i]+j和*(a+i)+j是a[i][j]的地址*(a[i]+j)或*(*(a+i)+j)是二维数组a[i][j]的值行指针列指针表示形式含义地址a二维数组名,数组首地址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列元素值20002000201020102018132000a[0][0]=12004a[0][1]=32008a[0][2]=5200Ca[0][3]=72010a[1][0]=92014a[1][1]=112018a[1][2]=13201Ca[1][3]=152020a[2][0]=172024a[2][1]=192028a[2][2]=21202Ca[2][3]=23第0行第1行第2行第0列第1列第2列第3列注意:a+1=*(a+1)=2010&a[1]=a[1]=2010a+i=&a[i]=a[i]=*(a+i)=&a[i][0]对二维数组inta[3][4],有a-----二维数组的首地址,即第0行的首地址a+i-----第i行的首地址a[i]*(a+i)------第i行第0列的元素地址a[i]+j*(a+i)+j-----第i行第j列的元素地址*(a[i]+j)*(*(a+i)+j)a[i][j]a+i=&a[i]=a[i]=*(a+i)=&a[i][0],值相等,含义不同a+i&a[i],表示第i行首地址,指向行a[i]*(a+i)&a[i][0],表示第i行第0列元素地址,指向列例用指针变量输出数组元素的值voidmain(){inta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};int*p;for(p=a[0];p<a[0]+12;p++){if((p-a[0])%4==0)printf("\n");printf("%4d",*p);}}运行结果:

1357911131517192123二维数组的指针变量指向二维数组元素的指针变量inta[3][4];a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]p对于m×n的数组,a[i][j]在数组中的相对位置计算公式为:i*n+j如:对于3×4的数组,其a[2][3]的相对位置为2*4+3=11指向由m个元素组成的一维数组的指针变量定义形式:数据类型

(*指针名)[一维数组维数];

例int(*p)[4];定义了指向包含4个整型元素的一维数组()不能少int(*p)[4]与int*p[4]不同(指针数组)p的值是一维数组的首地址,p是行指针可让p指向二维数组某一行如inta[3][4];int(*p)[4];p=a;一维数组指针变量维数和二维数组列数必须相同例输出二维数组任一行任一列元素的值voidmain(){inta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};int(*p)[4],i,j;p=a;scanf("i=%d,j=%d",&i,&j);printf("a[%d,%d]=%d\n",i,j,*(*(p+i)+j));}运行结果:i=1,j=2a[1][2]=13函数指针变量赋值:如p=max;,只需函数名,不必给参数函数返回值的数据类型专门存放函数入口地址可指向返回值类型相同的不同函数指向函数的指针变量定义形式:数据类型(*指针变量名)();

如int(*p)();函数调用形式:c=max(a,b);c=(*p)(a,b);*p代替函数名对函数指针变量pn,p++,p--无意义,函数指针只能指向函数入口处,而不能指向函数中间的某一条指令。()不能省int(*p)()与int*p()不同5

指针与函数函数指针:每一个函数都占有一段内存单元,一个函数在编译时被分配给一个入口地址,称为函数的指针。用函数名表示。可以用一个指针变量指向函数,然后通过指针变量调用该函数。max…...指令1指令2p例用函数指针变量调用函数,比较两个数大小intmax(intx,inty);voidmain(){inta,b,c;scanf("%d,%d",&a,&b);c=max(a,b);printf("a=%d,b=%d,max=%d\n",a,b,c);}intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}intmax(intx,inty);voidmain(){int(*p)(),a,b,c;

p=max;scanf("%d,%d",&a,&b);c=(*p)(a,b);printf("a=%d,b=%d,max=%d\n",a,b,c);}intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}用函数指针变量作函数参数例用函数指针变量作参数,求最大值、最小值和两数之和intmax(intx,inty);intmin(intx,inty);intadd(intx,inty);voidprocess(intx,inty,int(*fun)());voidmain(){inta,b;scanf("%d,%d",&a,&b);process(a,b,max);process(a,b,min);process(a,b,add);}voidprocess(intx,inty,int(*fun)()){intresult;result=(*fun)(x,y);printf("%d\n",result);}intmax(intx,inty){printf("max=");return(x>y?x:y);}intmin(intx,inty){printf("min=");return(x<y?x:y);}intadd(intx,inty){printf("sum=");return(x+y);}

7

指针数组和多级指针用于处理二维数组或多个字符串指针数组定义:数组中的元素为指针变量定义形式:[存储类型]

数据类型*数组名[数组长度];例int*p[4];指针所指向变量的数据类型指针本身的存储类型区分int*p[4]与int(*p)[4]指针数组赋值与初始化赋值:voidmain(){intb[2][3],*pb[2];

pb[0]=

温馨提示

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

评论

0/150

提交评论