C语言程序设计第8章指针地址和指针在计算机中,内存是用来存储程序和数据的部件。为了便于存储,通常把内存划分成许多个存储单元,并且对存储单元进行编号,存储单元的编号称为地址。地址通常以字节为单位进行编址。在C语言中地址是指数据在内存中存放的起始位置,如:变量(整型、浮点型、字符型、数组元素)的地址用&表示数组的地址用数组名表示。数组的地址就是数组中第一个元素的地址字符串常量的地址直接写出字符串,表示字符串的第一个字符的地址函数的地址用函数名表示。函数的地址就是函数的入口地址指针:存放地址的变量叫指针,也叫指针变量。指针变量的值是另一变量的地址,指针变量的值可以改变。指针变量的内容是所指变量的值。地址是一个常量如&i、数组名如a(或&a[0]),其值不能改变。指针变量指针变量的说明方式:类型说明符*标识符例:int*ptr,i=5;i是一个整型变量,ptr是一个指向整型变量的指针ptr=&i;&i是变量i的地址(指针常量),ptr是一个指针(指针变量)指针变量的运算符:*取指针变量所指的内容&取变量的地址上例中,*ptr==i&i==ptr&*ptr==ptr*&i==i注意:*出现在C程序的不同场合具有不同的含义。例8-1#includestdio.hvoidmain(){inta=5,b=10,c=15;int*pa,*pb,*pc;pa=&a;pb=&b;pc=&c;printf(%d\t%d\t%d\n,a,b,c);printf(%d\t%d\t%d\n,*pa,*pb,*pc);printf(%d\t%d\t%d\n,*&a,*&b,*&c);printf(%x\t%x\t%x\n,pa,pb,pc);printf(%x\t%x\t%x\n,&a,&b,&c);printf(%x\t%x\t%x\n,&*pa,&*pb,&*pc);printf(%x\t%x\t%x\n,&pa,&pb,&pc);}指针作为函数参数-比较下面的例子#includestdio.hvoidexchange(intx,inty){inttemp;temp=x;x=y;y=temp;}voidmain(){inta=5,b=8;exchange(a,b);printf(a=%d\tb=%d,a,b);}运行结果:a=5b=8#includestdio.hvoidexchange(int*x,int*y){inttemp;temp=*x;*x=*y;*y=temp;}voidmain(){inta=5,b=8;exchange(&a,&b);printf(a=%d\tb=%d,a,b);}运行结果:a=8b=5指针与数组在C语言中,数组名是指针常量,它代表的是数组的首地址,也是数组第一个元素的地址。设有:intdata[10];则:data==&data[0]data+i==&data[i]*(data+i)==data[i]例:8-3data→data[0]data+1→data[1]…data+i→data[i]例:使用指针作为形参和实参#includestdio.h#includeconio.hintmin(int*p,intn);main(){staticinta[7]={-1,9,7,3,-100,0,8};clrscr();printf(minvalue=%d,min(a,7));}intmin(int*p,intn){inti,minv;minv=*p;for(i=1;in;i++)if(minv*(p+i))minv=*(p+i);returnminv;}数组名做为实参,传递数组的首地址(地址常量)指针变量做为形参,接收数组的首地址例:以数组和数组元素形式处理指针#includestdio.h#includeconio.hintmin(int*p,intn);main(){staticinta[7]={-1,9,7,3,-100,0,8};clrscr();printf(minvalue=%d,min(a,7));}intmin(intp[],intn)*p改为p[],用下标法表示指针对象{inti,minv;minv=p[0];*p改为p[0]for(i=1;in;i++)if(minvp[i])minv=p[i];*(p+i)改为p[i]returnminv;}p[i]表示当前指针后第i个对象P[]形式上像数组,实际上按指针方式处理例:再探数组和指针#includestdio.h#includeconio.hvoidmain(){inta[7]={-1,9,7,3,-100,0,8};inti,*p;clrscr();p=a;for(i=0;i7;i++)printf(%d\t,a[i]);printf(\n);for(i=0;i7;i++)printf(%d\t,p[i]);}两次运行结果相同指针的运算p=&i将变量i的地址赋给指针pp=array将一维数组的首地址赋给指针pp=&array[i]将数组元素的地址赋给指针pp1=p2将指针变量p2的值赋给指针变量p1p1、p2指向同一个变量的地址p=NULL将指针p赋空值,不指向任何对象p++使p指向下一个对象区别于i++、i--P--使p指向前一个对象p+=i使p指向当前对象后第i个对象区别于x=x+i、x=x-ip-=i使p指向当前对象前第i个对象p+i指向当前对象p后第i个对象指针p不变p-i指向当前对象p前第i个对象指针运算例:#includestdio.hvoidmain(){inta[8]={-1,9,7,3,-100,0,8,5};floatb[8]={0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8};int*pa,*pa1;float*pb;pa=a;pb=b;printf(%u:%d\t\t%u:%3.1f\n,pa,*pa,pb,*pb);pa++;pb++;printf(%u:%d\t\t%u:%3.1f\n,pa,*pa,pb,*pb);pa+=3;pb+=3;printf(%u:%d\t\t%u:%3.1f\n,pa,*pa,pb,*pb);pa+2;pb+2;printf(%u:%d\t\t%u:%3.1f\n,pa,*pa,pb,*pb);printf(%u:%d\t\t%u:%3.1f\n,pa+2,*pa+2,pb+2,*pb+2);printf(%u:%d\t\t%u:%3.1f\n,pa,*(pa+2),pb,*(pb+2));pa=&a[3];pa1=&a[5];printf(%d\n,pa1-pa);if(papa1)printf();elseprintf();}字符指针字符指针指向字符串或字符型数组。例:#includestdio.hvoidmain(){chara[]=IamaTeacher.;char*ptr1=a,*ptr2=“YouareStudents.”;ptr1指向字符型数组a,ptr2指向字符串printf(“%c%c%c%c\n”,*ptr1,*(ptr1+2),*(ptr1+5),*(ptr1+7));显示:IaaTprintf(“%c%c%c\n”,*ptr2,*(ptr2+4),*(ptr2+8));显示:YaSprintf(“%s\n”,“SheisaStudent.”);对应%s的是字符串常量printf(“%s\n”,a);对应%s的是字符型数组首地址printf(“%s\n”,ptr2);对应%s的是字符指针变量}字符数组和字符指针处理字符串的区别字符数组由若干个元素组成,每个元素存放一个字符,若用来处理字符串,必须保证有串结束符’\0’。而字符指针变量用来存放字符串的首地址,不是用来存放整个字符串内容的。赋值或初始化方式不完全相同chardata[20]=“Thisisastring”;chardata[20];data=“Thisisastring”;没有意义char*ptr=“Thisisastring”;char*ptr;ptr=“Thisisastring”;等效字符数组和字符指针处理字符串的区别在说明一个字符数组后,其地址是确定的,有一个连续的区域用来存储数组的内容;而说明一个字符指针变量时,仅仅分配一个存储单元存放地址值,如果未赋值,它指向的对象是不确定的。chardata[20];scanf(“%s”,data);char*ptr;scanf(“%s”,ptr);错误,ptr未初始化,不知道往那存字符数组和字符指针处理字符串的区别字符指针变量的值可以改变,数组的首地址却不能改变。main(){char*ptr=“CLanguage”;ptr+=2;printf(“%s”,ptr);}main(){charstr[]=“CLanguage”;str+=2;printf(“%s”,str);}错误,数组地址不能改变应改成printf(“%s”,str+2);}指针数组由指针变量组成的数组,其说明格式为:类型说明符*数组名[常量表达式];例:int*p[3];分别说明了3个指针*p[0]、*p[1]、*p[2],指向3个整型变量或整型数组。例:int(*p)[3];说明了1个指针*p,指向有3个元素的一维整型数组。指向指针的指针inti,*p,**t;p=&i;t=&p;i是整型变量;p是指向整型变量i的指针;t是指向指针p的指针。指向函数的指针指向函数的指针就是指向函数的首地址,又称函数的入口地址。对于指向函数的指针而言,取内容表示执行由函数指针变量所指的函数。用户定义函数的函数名即是函数的首地址。指向函数的指针说明如下:类型说明符(*函数指针变量)();类型说明符(*函数指针变量)(参数列表);例:8-14#includestdio.hintmin(intm,intn){if(mn)returnm;elsereturnn;}voidmain(){inta,b,c,(*p)(int,int);定义函数指针变量p=min;函数名赋值给函数指针scanf(%d%d,&a,&b);c=(*p)(a,b);调用函数printf(a=%d,b=%d,min=%d\n,a,b,c);}例:8-15#includestdio.hintmax(intx,inty){return(xy)?x:y;}intmin(intx,inty){return(xy)?x:y;}intadd(intx,inty){return(x+y);}voidgeneral(intx,inty,int(*fun)(int,int)){intresult;result=(*fun)(x,y);printf(%d\n,result);}voidmain(){inta,b;printf(Enteraandb:);scanf(%d%d,&a,&b);printf(max=);general(a,b,max);printf(min=);general(a,b,min);printf(sum=);general(a,b,add);}字符串的输入输出方法字符串的输出方法:使用printf(“%s”,string)使用printf(“%c”,string[I])使用puts(string)字符串的输入方法:使用charstring[]=“Iamsorry”使用scanf(“%s”,string)以空格键、Tab键、和回车键作为结束使用gets(string)仅以回车键作为结束字符串处理函数字符串库函数,函数原型在string.h中。1.读取字符串函数gets(字符数组)2.输出字符串函数puts(字符数组)3.字符串拷贝函数strcpy(目的字符数组,源字符数组)4.部分字符串拷贝函数strncpy(目的字符数组,源字符数组,拷贝字符数)5.字符串比较函数strcmp(字符数组1,字符数