文章教程

全国计算机等级考试二级C语言9.2变量的指针和指向变量的指针变量

8/22/2020 10:24:52 PM 人评论 次浏览

9.2 变量的指针和指向变量的指针变量

考点1 指针变量的定义和引用

真考链接

对于考点1,最重要的是注意定义不同类型的指针用于指向相应类型的数据。属于简单识记知识点,在选择题中的考核概率为20%,在操作题中的考核概率为60%。

1. 指针变量的定义

定义指针变量的一般形式如下:

类型名 *指针变量名1,*指针变量名2,……;如:int*p,*t;。

以上定义语句中,p 和 t都是合法用户标识符,在每个变量前的星号(*)是一个类型说明符,用来标识该变量是指针变量。

为什么指针变量要有“基类型”呢?一个指针变量中存放的是一个存储单元的地址值。这里“一个存储单元”中的“一”所代表的字节数是不同的:对整型而言,它代表两个字节;对实型而言,它就代表4个字节,这就是基类型不同的含义。在以后的章节中将涉及指针的移动,也就是要对地址进行增减运算,这时指针移动的最小单位是一个存储单元,而不是1个字节。因此,对于基类型不同的指针变量,其内容(地址值)增1、减1所“跨越”的字节数是不同的。故指针变量必须区分基类型,基类型不同的指针变量之间不能混合使用。

2. 指针变量的引用

指针变量中只能存放地址(指针),将一个整型变量(或任何其他非地址类型的数据)赋给一个指针变量是不允许的。例如:

int*p;/*定义一个指向整型变量的指针*/

p=300;/*300为整数*/

是不合法的赋值。

与指针相关的两个运算符是“&”(取地址运算符)和“*”(指针运算符)。

小提示

在定义指针变量时,变量名前面的星号不可省略,若省略了星号说明符,就变成了把p和t定义为整型变量(int是类型名)。在这里,说明了p和t是两个指向整型(int类型)变量的指针,也就是说变量p和t中只能存放int类型变量的地址,这时称int是指针变量p和t的“基类型”。基类型用来指定该指针变量可以指向的变量的类型。

真题精选

【例1】若有说明:intn=2,*p=&n,*q=p;,则以下非法的赋值语句是(  )

A.p=q;    B.*p=q;    C.n=*q;    D.p=n;

【答案】D

【解析】选项A是两个指针变量之间的赋值;而选项B是把q的值赋给p指向的整型变量,虽然不常用,但也是对的;选项C是把q指向的变量的值赋值给n,也是没有问题的;而选项D中,整型数据和指针型数据之间不能进行赋值运算,所以是错误的

【例2】若有定义:intx,*pb;,则正确的赋值表达式是( )

A.pb=&x    B.pb=x    C.*pb=&x    D.*pb=*x

【答案】A

【解析】本题考查的是C语言中指针的定义和赋值原理

【例3】若有以下定义和语句

#include<stdio.h>

int a=4,b=3,*p,*q,*w;

p=&a;q=&b;w=q;q=NULL;

则以下选项中,错误的语句是(  )。

A.*q=0;    B.w=p;    C.*p=a;    D.*p=*w;

【解析】给一指针赋空值的正确语句是“q=NULL;”或“q='\0';”或“q=0;”。选项B的含义为使指针w指向指针p所指向的存储单元。选项C的含义为使指针p指向变量a所在的存储单元。选项D的含义为将指针w所指的变量值赋给指针p所指的变量。

【答案】A

【例4】若有定义:intx,*pb;,则正确的赋值表达式是( )

A.pb=&x    B.pb=x    C.*pb=&x    D.*pb=*x

【答案】A

【解析】本题的定义语句中,在pb的前面有一个*号说明符,表示pb是一个指针变量,按规定,在指针变量中只能存放存储单元(即变量)的地址。在定义语句中的类型名int说明了pb的基类型为int,因此pb中只能存放int类型变量的地址,即pb只能指向int类型的变量。已定义x为int类型变量,若其中已存放了整型数,则选项B中的赋值表达式pb=x企图把一个整数放到一个指针变量中,这是不允许的(赋值不兼容)。在C程序中,&号是求地址运算符,表达式&x的值是变量x在内存中的地址,而*号是间址运算符(与说明语句中的说明符*号的含义不同)。在选项C中,若pb已指向了一个整型变量(已放入了某整型变量的地址),则*pb就代表了此整型变量,所以赋值表达式*pb=&x企图把一个地址值放入到一个整型变量中,这是不允许的,地址值不可能转换为一个整数。间址运算符只能用于指针变量。在选项D中,赋值表达式右边出现了*x,把间址运算符*号用于一个整型变量是错误的。按定义,pb是一个指针变量,且只能存放int类型变量的地址,表达式&x取int型变量x的地址,表达式pb=&x把x的地址赋给了指针变量pb,所以选项A中的表达式是正确的。应掌握:①指针的定义方法;②指针变量的基类型;③所定义的指针变量中允许存放何种类型变量的地址;④求地址运算符(&)的正确运用;⑤间址运算符(*)的正确运用。若pb的基类型为double,则应掌握*pb出现在赋值号右边的含义是什么,出现在赋值号左边的含义又是什么。

【例5】设有定义

int n,*k=&n;

以下语句将利用指针变量k读写变量n中的内容,请将语句补充完整。

scanf("% d",【1】);

printf("% d\n",【2】);

【答案】【1】k 【2】*k

【解析】在语句“intn,*k=&n;”中,变量k中存放的是n的存储地址,*k表示变量n中的值,scanf函数需要地址值,而printf函数中的输出项是正常的基本类型,所以答案如上。

【例6】下列给定程序中函数fun()的功能是:实现两个变量值的交换,规定不允许增加语句和表达式

例如,变量a中的值原为8,b中的值原为3,程序运行后a中的值为3,b中的值为8。

请改正程序中的错误,使它得出正确的结果。

注意:不要改动main()函数,不得增行或删行,也不得更改程序的结构。

试题程序

#include <stdlib.h>

#include <conio.h>

#include <stdio.h>

int fun(int *x,int y)

{ int t;

/*****found*****/

t=x;x=y;

/*****found*****/

return(y);

void main()

{ int a=3,b=8;

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

b=fun(&a,b);

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

【答案】(1)t=*x;*x=y;

(2)return(t);或return t;

【解析】本题考查:指针型变量的使用;通过return语句完成函数值的返回

首先,定义变量t作为中间变量,然后进行数据交换,注意参数x是指针变量,交换时应使用*x,最后确定返回值,根据代码b=fun(&a,b);可以知道返回值将赋给变量b,而b中应存放交换前*x中的值,所以函数应返回变量t。

考点2 指针变量作为函数参数

真考链接

考查考点 2 的频率都非常高。属于重点理解重点掌握知识点。在选择题中的考核概率为30%。在操作题中,主要在编程题中考查此知识点,要求编写满足要求的程序段,考核概率为10%。

前面的章节中曾介绍过,函数参数可以是整型、实型、字符型等数据,指针类型数据同样也可以作为函数参数来进行传递。它的作用是将一个变量的地址传送到另一个函数中,参与该函数的运算。

如果想通过函数调用从而得到n个要改变的值,可以采用以下方法:

(1)在主调函数中设n个变量,分别用n个指针变量指向它们。

(2)然后将各个指针变量作为实参,即将这n个变量的地址传递给所调用的函数的形参。

(3)通过形参指针变量的改变,从而改变这n个变量的值。

(4)主调函数中就可以使用这些改变了值的变量。

形参指针变量的值的改变不能使实参指针变量的值发生改变。

常见问题

为什么指针变量要有“基类型”呢?

一个指针变量中存放的是一个存储单元的地址值。这里“一个存储单元”中的“一”所代表的字节数是不同的:对整型而言,它代表两个字节;对实型而言,它就代表4个字节。这就是基类型不同的含义。在以后的知识中将涉及指针的移动,要对地址进行增减运算,这时指针移动的最小单位是一个存储单元,而不是1个字节。因此,对于基类型不同的指针变量,其内容(地址值)增1、减1所“跨越”的字节数是不同的。故指针变量必须区分基类型,基类型不同的指针变量之间不能混合使用。

真题精选

【例1】有以下程序

void fun(char *c,int d)

{ *c=*c+1;d+ =1;

printf("% c,% c,",*c,d);

main()

{ char a= 'A',b= 'a';

fun(&b,a);printf("% c,% c\n",a,b);

程序运行后的输出结果是(  )。

A.B,a,B,a    B.a,B,a,B    C.A,b,A,b    D.b,B,A,b

【答案】D

【解析】本题考查了函数之间地址值的传递,当形参为指针变量时,实参和形参之间的数据传递是地址传递,可以在被调用函数中对调用函数中的变量进行引用,在被调用函数中直接改变调用函数中的变量的值,所以主函数中的b在代到fun()函数后将要发生变换,而a将不发生变换,所以在调用子函数时输出"b,B",返回到主函数中输出的是A和b,所以正确答案是选项D。

【例2】以下程序的输出结果是(  )

#include <stdio.h>

void fun(float *a,float *b)

{ float w;

*a=*a+*a;

w=*a;

*a=*b;

*b=w;

main()

{ float x=2.0,y=3.0;

float *px=&x,*py=&y;

fun(px,py);

printf("% 2.0f,% 2.0f\n",x,y);

A.4,3    B.2,3    C.3,4    D.3,2

【答案】C

【解析】主函数中定义了两个float变量x和y,以及基类型为float的指针变量px和py,并且把x和y的地址分别赋给了px和py。主函数中调用fun()函数时,把px和py作为实参,也就是把变量x和y的地址传送给形参。函数fun()为void类型,因此函数没有函数值返回。函数的形参a和b是两个基类型为float的指针变量。因此,在a和b中接受的是主函数中x和y的地址。在fun()函数体中,*a和*b将分别引用主函数中x和y的存储单元。fun()函数中,语句*a=*a+*a;的含义是两次取a所指对象(主函数的x)中的值相加,其和为4.0,赋给a所指对象(主函数的x)中,因此主函数的x中被重新赋值,x中的值变成4.0。fun()函数中后面的3条语句,是交换两个变量值的典型算法。先把a所指存储单元(主函数的x)中的值放在临时变量w中,然后把b所指存储单元(主函数的y)中的值放在a所指存储单元(主函数的x)中,最后把w中的值放入b所指存储单元(主函数的y)中。从而通过fun()函数,对主函数的x和y中的值进行交换。交换之前x中的值变成4.0,y中的值是3.0,经过交换,x中的值已变成3.0,y中的值为4.0。主函数的输出语句中,使用了“%2.0f”的格式说明,表明输出数据占两个字符位置,但“.0”的格式规定输出时不含小数点和小数,所以输出结果应是3,4。总结:本题给出了通过函数对两数进行交换的算法。注意:实参和形参之间仍遵循“按值传送”的规则,交换是通过指针间接进行的。

【例3】以下程序的输出结果是(  )

#include <stdio.h>

void sub(int x,int y,int *z)

{ *z=y-x;}

main()

{ int a,b,c;

sub(10,5,&a);sub(7,a,&b);sub(a,b,&c);

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

A.5,2,3    B.-5,-12,-7   C.-5,-12,-17   D.5,-2,-7

【答案】B

【解析】sub()函数为void类型,因此无函数返回值。函数的形参中,z是一个基类型为int的指针变量,因此它只能从实参接受一个int变量的地址。在sub()函数体中,语句*z=y-x;把形参y与x的差值放入形参z所指的存储单元中。在主函数中,3次调用sub()函数。第一次调用时,把10和5分别传送给形参x和y,把主函数中变量a(int类型)的地址传送给了形参z,所以形参z就指向了主函数中的变量a。在sub()函数中,语句*z=y-x;把-5放入z所指的存储单元中,如上所述,形参z已指向主函数中的变量a,因此,这时主函数中的变量a中就已被赋予-5。接着返回主函数。第二次调用时,把7传送给了形参x,把a中的值(-5)传送给了形参y,主函数中变量b(int类型)的地址传送给了对应形参中的指针变量z,所以形参z就指向了主函数中的变量b。执行sub()函数中的语句*z=y-x;把-12赋给主函数中的变量b,然后返回主函数。第三次调用时,把a中的值(-5)传送给了形参x,把b中的值(12)传送给了形参y,而形参指针变量z指向了主函数中变量c。sub()函数中,*z=y-x;把-12-(-5)的值放入z所指的变量c中,因此,c中就放入了-7。返回主函数后,输出a、b、c的值,因此输出的结果是-5、-12、-7。

【例4】以下程序的输出结果是(  )

#include<stdio.h>

sub(int *a,int n,int k)

{ if(k< =n)sub(a,n/2,2*k);

*a+ =k;

main()

{ int x=0;

sub(&x,8,1);

printf("% d\n",x);

A.1    B.8

C.7    D.4

【答案】 C

【解析】在main()函数中调用函数sub(&x,8,1)时,实参&x是将x的地址传给形参指针a,使指针a指向变量x,在sub ()函数中对指针a的操作将影响x。形参n的值为8,k的值为1。由于k<=n,递归调用sub(a,4,2),此时n的值为4,k的值为2,仍满足k<=n,再次递归调用sub(a,2,4),此时n的值为2,k的值为4,不满足k<=n,执行"*a+=k;"使*a的值为4,返回第一次递归调用,再执行"*a+=k;"使*a的值为6,返回第一次调用,再执行"*a+=k;"使*a的值为7,因此变量x的值为7。

【例5】下列给定程序中,函数fun()的功能是:将形参n所指变量中,各位上为偶数的数去掉,剩余的数按原来从高位到低位的顺序组成一个新数,并通过形参指针n传回所指变量。

例如,若输入一个数27638496,则新数为739。

请在标号处填入正确的内容,使程序得出正确的结果。

注意:部分源程序给出如下。不得增行或删行,也不得更改程序的结构。

试题程序

#include <stdio.h>

void fun(unsigned long *n)

{ unsigned long x=0,i;int t;

i=1;

while(*n)

{ t=*n% 【1】;

if(t% 2!=【2】)

{ x=x+t*i;i=i*10;

*n =*n /10;

*n=【3】;

main()

{ unsigned long n= -1;

while(n>99999999||n<0)

{ printf(" Please input(0 < n <100000000):");scanf("% ld",&n);}

fun(&n);

printf("\nThe result is:% ld\n",n);

【答案】【1】10 【2】0 【3】x

【解析】本题考查:求余运算;if语句条件表达式,指针变量作为函数参数。

标号【1】:通过t对10求余,取出该数值的各个位。

标号【2】:通过if条件语句实现奇偶数的判定。如果条件表达式对2求余为0即是偶数,反之是奇数。

标号【3】:最后将剩余的数赋给n指向的元素。

教程类别