指针150指针一、指针与指针变量的概念、指针与地址运算符1.指针:是指一个变量的地址,通过变量的地址指向的位置可以找到变量的值,用来存放地址的变量称为指针变量,指针变量存放变量的地址,不能将非地址值赋给指针变量。2.定义指针变量的一般形式为:类型名*指针变量1,*指针变量2,…;类型名规定了定义的指针变量所指向的存储单元中存放的数据类型,*号表明后面的变量是指针变量。3.一个指针变量只能指向同一类型的变量。4.与指针和指针变量有关的两个运算符:(1)*:指针运算符(或称”间接访问”运算符),通过*号可以引用一个存储单元的值。(2)&:取地址运算符二、变量、数组、字符串、函数、结构体指针及指针变量1.变量的指针:即变量的地址。如inta;则&a即为变量a的指针(地址)。指向变量的指针变量:即存储变量的地址的变量。如:inta;int*p=&a;则p是指向变量a的指针变量。2.组的指针:是指数组的起始地址,C语言中的数组名字代表数组的首地址;考点与重难点解析备必知识◆考点精要◆重点难点1111大纲要求1.指针与指针变量的概念,指针与地址运算符。2.变量、数组、字符串、函数、结构体的指针以及指向变量、数组、字符串、函数、结构体的指针变量。通过指针引用以上各类型数据。3.用指针作函数参数。4.返回指针值的指针函数。5.指针数组,指向指针的指针,main函数的命令行参数。指针151数组元素的指针:是数组元素的地址;指向数组的指针变量:如inta[8];int*p=a;则p就是指向数组a的指针变量;C语言规定数组名代表数组的首地址,也就是第一个元素的地址。3.字符串的指针和指向字符串的指针变量:我们可以通过定义说明一个指针指向一个字符串。C语言将字符串隐含处理成一维字符型组,但数组的每个元素没有具体的名字,这一点跟字符数组不一样,要引用字符串中的某个字符,只能通过指针来引用:如char*str=”abcdefg”;则*(str+2)表示的是字符‘c’。C语言中没有对字符串进行合并、比较和赋值的运算符,但通过字符指针,可利用几乎所有版本的C语言中都提共了有关的库函数来实现。如p1、p2都是指向字符串的指针,或p1、p2都是已维字符数组的名字,则:(1)strcat(p1,p2)函数:连接两个字符数组中的字符串。(2)strcpy(p1,p2)函数:字符串拷贝函数(3)strcmp(p1,p2)函数:字符比较函数(4)strlen(p1)函数:测试字符串长度的函数(5)strlwr(p1)函数:将字符串中大写字母转换成小写字母(6)strupr(p1)函数:将字符中小写字母转换成大写字母4.函数的指针和指向函数的指针变量函数的指针即函数的入口地址;向函数的指针变量的一般形式为:数据类型(*指针变量名)();其中“数据类型”是指函数返回值的类型。函数的调用可以通过函数名调用,也可以通过函数指针调用(即用指向函数的指针变量调用)。指向函数的指针变量,它不是固定指向哪一个函数,而只是定义了这样一个类型的变量,它专门用来存放函数的人口地址。在程序中把哪一个函数的地址赋给它,它就指向哪一个函数。在一个程序中,一个指针变量可以先后指向不同的函数。在给函数指针变量赋值时,只需给出函数名而不必给出参数。因为函数指针赋的值仅是函数的人口地址,而不涉及到实参与形参的结合问题。对指向函数的指针变量,以下表达式p+n,p++,p――等都没有意义的。5.结构体的指针与指向结构体的指针变量一个结构体变量的指针就是该结构体变量所占据的内存段的起始地址。可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。三、指针做函数参数函数的参数不仅可以是整型、实型、字符型等数据,还可以是指针类型,它的作用是将一个变量的地址传送到另一个函数中。使用指针作为函数参数可再调用一个函数时得到多个由被调函数改变的值。因此可以利用这一规律,很容易地编写当主调函数需要多个被改变的值返回的函数。指针152四、返回指针值的指针函数一个函数可以返回一个整型值、字符值、实型值等,也可以返回指针型的数据,即地址,这种带回指针值的函数,一般的定义形式为:数据类型*函数名(形参表);返回指针的函数非常有用,许多库函数都是返回指针值的,在调用时一般要设立相应类型的指针来接受返回的值。五、指针数组、指向指针的指针1.指针数组指的是一个数组,其元素均为指针类型数据,也就是说,指针数组中的每个元素都是指针变量,指针数组的定义形式为:数据类型*数组名[数组长度]这里[]优先级高于*,所以定义的首先是个数组,再与*结合,表明数组的每个元素是一个指针。指针数组使同时处理多个字符串更加方便。2.指向指针的指针:是指向指针数据的指针变量,一个指向指针数据的指针变量的定义形式为:数据类型**变量名;3.指向一维数组的指针:其定义形式为:数据类型(*指针变量)[常量]例如:int(*ptr)[m];其中,ptr是一个指针变量,它指向一个一维数组,该数组有m个元素,每个元素都是int型。注意运算符()的优先级高于[],所以定义ptr的首先是个指针,然后再与[]结合,表示是一个指向一维数组的指针。4.main函数的命令参数:指针数组的一个重要应用一般来说,main函数后的括号中是空的,即没有参数。实际上main可以有参数,其一般格式为:main(intargc,char*argv[])由于main函数是由系统调用的,其他函数形参的值可以通过函数调用语句的实参中得到,而main函数的形参值不能从程序中得到,但可以在操作系统状态下,将实参和命令一起给出从而使main函数的形参得到值。命令行的一般形式:命令名参数1参数2…参数n形参argc表示命令行中参数的个数(注意:文件名也作为一个参数),argv是一个指向字符串的指针数组,分别指向命令行中的各个字符串,如argv[0]指向文件名(也即命令)。mian函数中的形参也可不命名为argc和argv,可以是任意的名字,只是人们的习惯而已。【例题1】以下程序调用findmax函数返回数组中的最大值(2002.04)findmax(int*a,intn){int*p,*s;for(p=a,s=a;p-an;p++)典型试题精解经典例题◆相关知识◆解题分析2222指针153if()s=p;return(*s);}main(){intx[5]={12,21,13,6,18};printf(%d\n,findmax(x,5));}在下划线处应填入的是()。A.psB.*p*sC.a[p]a[s]D.p-ap-s解析根据题意,程序中下划线处应该是将数组中各元素的值与s指针所指向的存储空间(保存的是已比较元素中的最大值)的值进行比较,选项A中是两个指针的比较,选项C中的a[p]和a[s]根本就不能表示数组的元素,选项D也不能表示元素的比较本,应该选择B。答案B【例题2】以下程序的输出结果是()。(2002.04)#includestdio.h#includestring.hmain(){charb1[8]=abcdefg,b2[8],*pb=b1+3;while(--pb=b1)strcpy(b2,pb);printf(%d\n,strlen(b2));}A.8B.3C.1D.7解析本题注意指针pb的移动,循环开始时,pb指向下图所示的位置,继续循环时,pb将向左移动,直到pb指向’a’,因此通过循环最后考备到b2数组中的字符串就是b1数组中保存的字符串,所以本题应选择D。答案D【例题3】若有说明语句:inta,b,c,*d=&c;,则能正确从键盘读入三个整数分别赋给变量a、b、c的语句是()。(2002.04)A.scanf(%d%d%d,&a,&b,d);B.scanf(%d%d%d,&a,&b,&d);C.scanf(%d%d%d,a,b,d);D.scanf(%d%d%d,a,b,*d);解析scanf函数中的参数应该是取变量的地址,所以只有A是对的。答案A【例题4】以下程序的输出结果是()。(2002.04)charcchar(charch){if(ch=‘A’&&ch=‘Z')ch=ch-‘A'+‘a';returnch;}指针154main(){chars[]=ABC+abc=defDEF,*p=s;while(*p){*p=cchar(*p);p++;}printf(%s\n,s);}A.abc+ABC=DEFdefB.abc+abc=defdefC.abcaABCDEFdefD.abcabcdefdef解析cchar(charch)函数的功能是将ch变量中的字母转变成小写字母,因为ch=ch-‘A'+‘a’=ch-65+97=ch+32,原来就是小写字母的话,就不转换。因此应选择B。答案B【例题5】若有以下定义和语句:(2002.04)ints[4][5],(*ps)[5];ps=s;则对s数组元素的正确引用形式是()。A.ps+1B.*(ps+3)C.ps[0][2]D.*(ps+1)+3解析本题定义的ps是指针数组,即数组中的每个元素是指针,ps=s表示ps指向了二维数组,其中ps[0]指向二维数组s的下标为0的行。A选项中ps+1表示的是s数组下标为1的行的首地址;选项B中*(ps+3)表示的是s数组中s[3][0]元素的地址;D选项中表示的是s数组中s[1][3]元素的地址,只有C表示的是s数组中s[0][2]元素的值。本题应选择C。答案C【例题6】不合法的main函数命令行参数表示形式是()。(2002.04)A.main(inta,char*c[])B.main(intarc,char**arv)C.main(intargc,char*argv)D.main(intargv,char*argc[])解析main函数命令行参数中第一个参数是指记录命令行中参数的个数(注意文件名也作为一个参数),第二个参数是一个指向字符串的指针数组,指针数组的元素记录的是命令行中各个字符串的首地址。两个参数的名字可以是任意的,只是人们习惯用argc和argv。由此可知:选项A和D是正确的,而选项B的第二个参数是指向指针的指针,用它指向命令行各字符串的首地址构成的指针数组;C选项的第二个参数是字符指针,它不能指向多个字符串,是错的。所以应选择C。答案C【例题7】以下定义语句中,错误的是()。(2001.09)A.inta[]={1,2};B.char*a[3];C.chars[10]=test;D.intn=5,a[n];解析定义数组时,数组的长度只能是常量或常量表达式,不能是变量,所以D是错误的.应选择D。答案D指针155【例题8】以下选项中,不能正确赋值的是()。(2001.09)A.chars1[10];s1=Ctest;B.chars2[]={'C','t','e','s','t'};C.chars3[20]=Ctest;D.char*s4=Ctest\n解析选项B、C都是在定义字符数组时初始化的,是正确的;选项D定义一个字符指针指向一个字符串常量也时正确的;只有A是错误的,不能用s1=Ctest的形式给字符数组赋值,如果定义完字符数组后,需要给字符数组赋值的话,只能用strcopy(s1,Ctest)给s1赋值。所以应选择A。答案A【例题9】下列程序段的输出结果是()。(2001.04)A.2143B.1212C.1234D2112voidfun(int*x,int*y){printf(%d%d,*x,*y);*x=3;*y=4;}main(){intx=1,y=2;fun(&y,&x);printf(%d%d,x,y);}解析注意本题中函数的形参是指针,调用函数时的实参是整型变量的地址,在fun函数中是先输出形参变量x、y所指存储空间的值(注意形参的x指向实参的y,形参y指向实参的x)21,然后再改变形参x、y所指存储空间的值(*x=3;*y=4),返回主函数后,实参变量的值也