您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 质量控制/管理 > 最全的C语言指针详解
第6章指针6.1指针定义与使用6.2指针与函数6.3指针与数组6.4指针与字符串6.5指针数组与多级指针6.6指针与动态内存分配6.7指针的深层应用6.1指针的引出一.地址与指针1.地址与取地址运算C程序中的变量在内存中占有一个可标识的存储区,每一个存储区是由若干个字节组成,每一个字节都有自己的地址,而一个存储区的地址是指该存储区中第一个字节的地址C语言允许在程序中使用变量的地址(通过地址运算符&可得到)如:floatx;变量x的地址----&xinta[10];数组变量a的地址----数组名a2.指针与指针变量(1)变量的访问方式①直接访问:通过变量名或地址访问变量的存储区例:scanf(“%d”,&x);x=sqrt(x);printf(“%d”,x);②间接访问:将一个变量的地址存放在另一个变量中.如将变量x的地址存放在变量p中,访问x时先找到p,再由p中存放的地址找到xpx201210101010(2)指针:一个变量的指针就是该变量的地址(指针就是地址)(3)指针变量:存放变量地址的变量,它用来指向另一个变量二、指针变量的定义1.格式:数据类型*指针变量名;例int*p1;char*p2;2.说明:(1)在变量定义时,*号表示该变量是指针变量(注意:指针变量是p1,p2,不是*p1,*p2)(2)定义指针变量后,系统为其分配存储空间,用以存放其他变量的地址,但在对指针变量赋值前,它并没有确定的值,也不指向一个确定的变量例:intx,*p;x=5;px2012101051234注:指针变量p的值是随机值,此时p和x并无关联(3)使指针变量指向一个确定的变量必须进行赋值intx,*p;x=5;p=&x;px2012101051010三、指针变量的引用1.指针运算符*(1)p与*p不同,p是指针变量,p的值是p所指向的变量的地址*p是p所指向的变量,*p的值是p所指向的变量的值*p的值为5(*p表示x),而p的值为1010(2)引用指针变量时的*与定义指针变量时的*不同定义变量时的*只是表示其后的变量是指针变量inta,*p;p=&a;scanf(“%d”,p);printf(“%d\n”,*p);*p=12;printf(“%d\n”,*p);pa201210105101012让p指向a对a重新赋值等价于a=12即&a2.&与*p=&a;*&a*(&a)*pa&*p&(*p)&a2abcd53.*与++,--inta=2,b=5,c,d,*p;p的值为a的地址,*p的值为2p的值不变,*p的值为3(2)c=*p++;c=*(p++);{c=*p;p++;}执行后c的值为3,*p的值为5(3)d=*++p;d=*(++p);{++p;d=*p;}执行后d的值为3,*p的值为3p201210101010(1)p=&a;(*p)++;(等价于a++;)10123310143例6.2#includestdio.hvoidmain(){int*p1,*p2,*p,a,b;scanf(“%d%d”,&a,&b);p1=&a;p2=&b;if(ab){p=p1;p1=p2;p2=p;}printf(“a=%d,b=%d\n”,a,b);printf(“max=%d,min=%d\n”,*p1,*p2);}abp1p2p&a&b&a&b&a59输出结果:a=5,b=9max=9,min=5一、指针变量作函数参数例:2个数按大小顺序输出#includestdio.hvoidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}voidmain(){inta,b;scanf(“%d%d”,&a,&b);if(ab)swap(a,b);printf(“a=%d,b=%d\n”,a,b);}abxytemp5说明:该程序不能实现a和b的交换因为实参a,b对形参x,y是“值传递”,x和y的变化不影响a和b所以输出为:a=5,b=99mainswap559956.2指针与函数例6.3①#includestdio.hvoidswap1(int*p1,int*p2){inttemp;temp=*p1;*p1=*p2;*p2=temp;}voidmain(){inta,b,*pt1,*pt2;scanf(“%d%d”,&a,&b);pt1=&a;pt2=&b;if(ab)swap1(pt1,pt2);printf(“a=%d,b=%d\n”,a,b);}abp1p2temp&b&apt1pt25说明:这种方法是交换p1和p2所指向的变量的值,即交换main函数中a和b的值所以输出为:a=9,b=5mainswap159&a&b95例6.3②#includestdio.hvoidswap2(int*p1,int*p2){int*temp;*temp=*p1;*p1=*p2;*p2=*temp;}说明:这种方法可能会破坏系统的正常工作状态,因为temp是一个指针变量但是在函数中并没有给temp一个确定的地址,这样它所指向的内存单元是不可预见的,而对*temp的赋值可能带来危害abpt1pt2main&a&bp1p2temp&b&aswap2?随机值55959例6.3③#includestdio.hvoidswap3(int*p1,int*p2){int*p;p=p1;p1=p2;p2=p;}p1p2p&a&a&b这种方法是交换形参p1和p2的值,使它们的指向发生改变,但是main函数中的a和b的值并没有进行交换所以输出为:a=5,b=95a9b&apt1&bpt2main&b&aswap3前面我们用到的函数,有些无返回值,有些有返回值,返回值类型多为int,float,char.一个函数的返回值也可以是一个指针类型的数据(即地址)定义函数:数据类型*函数名(形参表列){函数体;}例:int*fun(inta,intb){函数体;}说明:定义一个返回指针值的函数与以前定义函数格式基本类似,只是在函数名前加*,它表明该函数返回一个指针值,而这个指针值是指向一个int型数据二、函数返回指针例:#includestdio.h#includestring.h#defineSIZE100charbuf[SIZE];char*p=buf;char*alloc(intn){char*begin;if(p+n=buf+SIZE){begin=p;p=p+n;return(begin);}elsereturn(NULL);}voidmain(){char*p1,*p2;inti;p1=alloc(10);strcpy(p1,”123456789”);p2=alloc(5);strcpy(p2,”abcd”);printf(“buf=%p\n”,buf);printf(“p1=%p\n”,p1);printf(“p2=%p\n”,p2);puts(p1);puts(p2);for(i=0;i15;i++)printf(“%c”,buf[i]);}buf[0]buf[1]::buf[9]buf[10]:buf[14]buf[15]::buf[99]bufpbuf+10p1p2mainbeginnallocbufbufbuf+1012:9\0a:\010buf+15beginnallocbuf+105函数的指针:函数的入口地址在程序执行过程中调用函数时,计算机会转去执行函数体内的语句,因此计算机必须知道函数在什么地方。实际上函数在内存中也要占据一片存储单元,这片存储单元一个起始地址,我们称其为函数的入口地址,即函数的指针,这个函数的入口地址是用函数名来表示。因此我们可以定义一个指针变量,让它的值等于函数的入口地址,然后可以通过这个指针变量来调用函数,该指针变量称为指向函数的指针变量三、指向函数的指针指向函数的指针变量1.定义格式:数据类型(*指针变量名)(形参表列);int(*pt)(intarr[],intn);说明:①数据类型:指针变量所指向的函数的返回值类型②形参表列:即指针变量所指向的函数的形参表列③格式中的小括号不能省略2.应用(1)让指针变量指向函数pt=add;因为函数名为函数的入口地址,所以直接将函数名赋给指针变量即可(2)使用指针变量调用函数格式:(*指针变量名)(实参表列)例求一维数组中全部元素的和#includestdio.hintadd(intb[],intn);voidmain(){inta[6]={1,3,5,7,9,11},total;int(*pt)(intb[],intn);pt=add;total=(*pt)(a,6);printf(“total=%d\n”,total);}intadd(intb[],intn){inti,sum=0;for(i=0;in;i++)sum=sum+b[i];return(sum);}定义指向函数的指针变量令指针变量pt指向函数add通过pt调用函数add6.3指针与数组一.一维数组与指针1.一维数组及元素的地址表示inta[5]={1,2,3,4,5};数组的地址:a元素地址*aa[0]&a[0]a*(a+1)a[1]&a[1]a+1*(a+2)a[2]&a[2]a+2*(a+3)a[3]&a[3]a+3*(a+4)a[4]&a[4]a+42.用指针变量引用数组元素(1)定义指针变量int*p,a[5]={1,2,3,4,5};p=a;(2)引用数组元素下标法地址法指针法第k个元素a[k]*(a+k)*(p+k)第k个元素的地址&a[k]a+kp+k注意:指针变量也可以加下标p[k]等价于a[k]①分别用三种方法输出数组元素,其效率不同,下标法与地址法的效率相同,指针法的效率较快②用指针变量访问数组元素时要注意下标是否越界例:将数组a中全部元素加1,再输出a#includestdio.hvoidmain(){inta[5]={1,3,5,7,9},*p,j;for(p=a;pa+5;p++)printf(“%3d”,*p);printf(“\n”);for(j=0;j5;j++)a[j]=a[j]+1;for(j=0;j5;j++)printf(“%3d”,*(p+j));printf(“\n”);}p=a;13579aa+1a+2a+3a+4246810p可以用p++,但不能用a++因为a代表数组的起始地址它是地址常量,不能改变而p是一个指针变量使用指针变量时要注意它的当前值3.指向数组的指针变量作函数参数例6.7①实参和形参都用数组名#includestdio.hvoidinv1(intx[],intn){inttemp,i,j,m=(n-1)/2;for(i=0;i=m;i++){j=n-1-i;temp=x[i];x[i]=x[j];x[j]=temp;}}voidmain(){inti,a[6]={1,3,4,6,7,9};inv1(a,6);for(i=0;i6;i++)printf(“%3d”,a[i]);printf(“\n”);}a[0]a[1]a[2]a[3]a[4]a[5]x[0]x[1]x[2]x[3]x[4]x[5]134679976431maininv1例6.7②实参用数组名,形参用指针变量#includestdio.hvoidinv2(int*x,intn){inttemp,m=(n-1)/2;int*p,*i,*j;i=x;j=x+n-1;p=x+m;for(;i=p;i++,j--){temp=*i;*i=*j;*j=temp;}}voidmain(){inti,a[6]={1,3,4,6,7,9};inv2(a,6);for(i=0;i6;i++)printf(“%3d”,a[i]);printf(“\n”);}134679a[0]a[1]a[2]a[3]a[4]a[5]axai6na+5ja+2pinv29173642mtemp1a+
本文标题:最全的C语言指针详解
链接地址:https://www.777doc.com/doc-4359919 .html