C语言课件指针知识点与例题剖析.docx
- 文档编号:10838891
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:52
- 大小:44.81KB
C语言课件指针知识点与例题剖析.docx
《C语言课件指针知识点与例题剖析.docx》由会员分享,可在线阅读,更多相关《C语言课件指针知识点与例题剖析.docx(52页珍藏版)》请在冰豆网上搜索。
C语言课件指针知识点与例题剖析
1对于变量x,其地址可以写成________;对于数组y[10],其首地址可以写成________或__________;对于数组元素y[3],其地址可以写成__________或_________。
【分析】变量的地址可以写成“&变量名”。
数组的首地址就是数组名,也可以写成第1个元素的地址“&数组名[0]”。
数组元素的地址可以写成“&数组元素”,也可以写成“数组首地址十下标”。
【答案】&x
y
&y[0]
&y[3]
y+3
2设有定义语句“intk,*p1=&k,*p2;”,能完成表达式“p2=&k”功能的表达式可以写成_______________。
【分析】注意原来表达式“p2=&k”的主要功能是将变量k的地址存放到指针变量p2中。
现
在变量k的地址已经存放在指针变量pl中,所以完成“p2=&k”功能的表达式是:
p2=p1.
【答案】p2=p1
3设有两条语句“inta,*p=&a;”和“*p=a;”,则下列说法中正确的是()
①两条语句中的“*p”含义完全相同
②两条语句中的“*p=&a”和“*p=a”功能完全相同
③第1条语句中的“*p=&a”是定义指针变量p并对其初始化
④第2条语句中的“*p=a”是将a的值赋予变量p
【分析】分析备选答案①:
第1条语句是数据定义语句,其中的“*p”表示定义的变量p是指针型变量;第2条语句是赋值语句,其中的“*p”代表它所指向的变量a,所以该备选答案是错误的,不符合题意。
分析备选答案②:
第1条语句中的“*p=&a”是将变量a的地址以初值方式赋予指针变量p;而第2条语句中的“*p=a”是将变量a中的值赋予指针变量P指向的变量(注意也是a,即该语句的作用和a=a完全相同),显然该备选答案是错误的,不符合题意。
再分析备选答案③:
显然该答案是正确的,符合题意。
至于备选答案④,显然是错误的“*p”是代表指针变量p指向的变量,不能代表指针变量p。
【答案】③
4设有定义语句“intx,*p=&x;”,则下列表达式中错误的是()
①*&x ②&*x ③*&p ④&*p
【分析】注意“*”和“&”运算将是同一优先级别的,结合性是自有向左。
接着来分报备选答案①:
&x代表变量x的地址,*(&x)代表“&x”地址对应的变量,即变量X,一股说“*&变量”就是该变量,所以该答案是正确的,不符合题意。
备选答案②中的“*x”是错误的,因为x是普通变量,不是指针型变量,而运算符“*”的运算对象必须是地址,所以该答案符合题意。
显然备选答案③和④都是正确的。
我们来分析一下。
备选答案③的格式属于“*&变量”,所以其结果为指针型变量p,是正确的。
备选答案④中的“*P”代表指针变量P指向的变量x,(*p)代表变量X的地址,也是正确的。
一般说“&*指针变量”,则代表指针变量指向的变量的址。
【答案】②
5设有定义语句“floats[10],*p1=s,*p2=s+5;”,下列表达式中错误的是()
①p1=0xffff ②p2-- ③p1-p2 ④p1<=p2
【分析】当两个指针变量指向同一个数组时,每个针变量都可以进行增l、减1运算,两个指针变量之间可以进行减法运算和关系运算。
显然备选答案②、③。
④是正确的,不符合题意,只有备选答案①才是错误的,符合题意。
对备选答案①的分析也很简单,因为C语言规定,所以的地址表达式中,不允许使用具体的整数来表示地址。
【答案】①
6有下列定义语句“chars[]={"12345"},*p=s;”,下列表达式中错误的是()
①*(p+2) ②*(s+2 ③p="ABC" ④s="ABC"
【分析】分析备选答案①:
指针变量p已经指向数组s首地址,则p+2代表数组元素s[2]的地址,*(p+2)就是代表数组元素s[2],所以是正确的,不符合题意。
分析备选答案②:
s是数组名,代表数组首地址,s+2代表数组元素a[2]的地址,*(S+2)代表数组元素s[2],和备选答案①一样,也不符合题意。
分析备选答案③:
C语言规定,在程序中可以使用赋值运算符将字符串常量直接赋予字符型指针变量,所以该备选答案也是正确的,不符合题意。
只有备选答案④是错误的,符合题意。
原因是C语言规定,在程序中不允许将字符串常量以赋值语句方式直接赋予字符型数组。
【答案】④
7设有语句“floatx[4][10],*p=x;”,则下列表达式中不属于合法地址的表达式是()
①&x[1][2] ②*(p+1*10+2)
③x[1] ④p+1*10+2
[分析]分析备选答案①:
x[1][2]是合法的数组元素,所以“&x[1][2]”表示数组元素x[l][2]的地址。
分析备选答案②:
由于指针变量指向二维数组首地址,“*(指针变量十行下标*列长度十列下标)”是表示数组元素“数组名[行下标][列下标]”的,不表示地址,所以该答案符合题意。
至于备选答案③,x[l]代表数组X中行下标为1的所有元素组成的一维数组名,即该一维数组的首地址,所以是一个地址表达式。
备选答案④中的表达式是代表数组元素x[1][2]的地址的,具体分析可以参看上面备选答案②中的分析。
【答案】②
8设有定义语句“doubled[3][5]={{1},{2},{3}},(*p)[5]=d;”,则下列表达式中值不为0.0的表达式是()
①*&d[1][2] ②p[1][2]
③*(p+1*5+2) ④*(*(p+l)+2)
【分析】首先看看数组d中各元素的初值,显然d[0][0]的初值为1.0、d[l][0]的初值为2.0.
d[2][0]的初值为3.0,其余元素的初值均为0.0。
接着分析备选答案①:
*&d[1][2]就是d[l][2],所以其值为0.0,不符合题意。
分析备选答案②:
p[1][2]就是d[1][2],显然其值为0.0,不符合题意。
再分析备选答案③:
该表达式运算后的结果相当于*(p+7),由于指针变量p是指向长度为5的一维数组的,所以,这个表达式代表地址,其值不是0.0,符合题意。
显然备选答案④中表达式的值为0.0;因为该表达式相当于数组元素d[1][2]。
【答案】③
9设有定义语句“chars[3][20],(*p)[20]=s;”,则下列语句中错误的是()
①scanf("%s",s[2]); ②gets(*(p+2));
③scanf("%s",(p+2)+0); ④gets(s[2][0]);
【分析】分析备选答案①、③,都是通过scanf()函数输入一个字符串,该函数中的第2个参数要求是地址。
备选答案①中的S[2]是一个地址,表示输入的字符串存人字符数组s的第2行,所以是正确的。
由于指针变量p是指向长度为20的一维数组,所以备选答案③中的*(p+2)+0相当于s[2][0]的地址,也是正确的。
备选答案②、④是通过gets(输入字符串的,该函数的参数也是地址。
分析备选答案②中的*(p+2)字符数组s的第2行组成的一维数组的首地址,所以是正确的。
备选答案④中的s[2][0]是数组元素,不是地址,所以是错误的。
【答案】④
10设有下列程序段,该程序段输出的结果是
intk[2]={5,4},*P[2];
p[o]=k,p[l]=k+l;
prinif("%d",*p[1]);
【分析】从定义语句中可以看出,p是一个指针型数组,共有两个数组元素:
p[0]和p[1]。
两个赋值表达式组成的逗号表达式使得p[0]指向整型数组元素k[0],其值为5;p[1]指向整型元素k[l],其值为4。
输出语句中的输出表达式“*P[1]”是代表指针数组元素p[l]指向的整型数组元素k[1]的,其值为4。
【答案】4
11设有下列定义语句,则表达式“**p2”的值是_______________,表达式“*(*p2+l)”的值是_________________。
intx[3]={1,2,3},*p1=x,**p2=&p1;
【分析】从定义语句中可以看出,pl是指向整型数组X首地址的一级指针变量,p2是指向一级指针变量pl的二级指针变量。
从运算符“*”的结合性是自右向左的来看,表达式**p2相当于肝*(*p2,*p2相当于p1,所以**p2相当于*pl,由于一级指针变量p1指向的是数组X的首地址,即x[0]的地址,所以其值为x[0]的值,等于1。
第2个表达式*(*p2+1相当于*(p1+1),而pl+l相当于数组元素x[1]的地址,所以该表达式的值就是数组元素x[1]的值,等于2.
【答案】1
2
12设有下列程序,假定该程序运行后的输出是:
234。
请填写程序中缺少的语句成份。
main()
{char*p="12345678";
while(____________)
{printf("%c",*p+1);
p++;
}
}
【分析】从数据定义语句中看出,字符型指针变量指向字符串"12345678",即指针变量p指向
第1个字符'l'。
由于程序所缺少的是控制循环的条件,假定第1次执行循环体时条件成立,输出的结果是"*p+1",即是指向字符'l'的,'1'+1的结果是字符'2',输出结果为2,与题目要求一致,然后执行p++,使p指向第2个字符'2'。
显然第2次执行循环体输出结果为字符'3',符合题目要求。
第3次执行循环体输出字符是'4',也符合题目要求。
注意此时p已经指向字符串中的第4个字符'4',显然不能再执行循环体了,否则将输出字符'5'。
可以看出,所缺少的控制循环条件是当p指向字符串中第4个字符'4'时必须退出循环。
这个条件很容易写成“p指向的字符不是'4'”。
具体来说,这个条件表达式可以写成“*p!
='4'”,也可以写成“*p<'4'”或者“*p<='3'”等等。
【答案】*p='4'或者*p<'4'或者即*p<='3'
13下列程序的功能是输入一个字符串存入字符数组a中,然后将其中的所有字符'\DOWN'删除后再存入字符数组b,最后将字符数组b中的字符串输出。
请填写程序中缺少的语句。
#include”string.h”
main()
{chara[81],b[8l],*p1=a,*p2=b;
gets(p1);
while(*p1='\0')
if(*p1==‘\\')
___________________
else
*p2++=*p1++;
puts(b);
}
【分析】程序中的当型循环是完成删除数组a中存放的字符串中字符'\'的,分析控制这个循环的条件可知,这是依次处理存放在字符数组a中每个字符的标准程序段。
循环体中是一条双分支语句,条件是当前字符(*p1)是否等于字符'\',如果不是'\'字符,则“将数组a中当前字符(*pl)复制到数组b的当前位置(*p2),然后再修改p1和p2两个指针变量(各加1,使其指向后一个字符的位置)。
如果上述条件不成立(当前字符是‘\'),按照题目中给出的处理要求,这个字符不复制到数组b中,显然不需要执行“*p2=*p1”,此外,指向数组b的指针变量p2也不需要加1,但是,指向数组a的指针变量p1需要加1,使其指向当前的'\'字符后面的字符,所以,这个地方缺少的语句应该是完成“p1加1”任务的,显然这个语句可以是“p1++”,或者“p1+=1”或者“p1=p1+1”。
【答案】p1++:
或者 p1+=l;或者 p1=p1+1;
14阅读下列程序,写出程序运行的输出结果。
main()
{chara[20]={”1A2B3C”},b[20],*p1=a,*p2=b;
do{if(!
((*p1>='O'&&*p1<='9'))
{*p2=*p1;
p2++;
*p2=*p1;
}
else
*p2=*p1;
p1++,p2++;
}
while(*p1='\0');
*p2=*p1;
printf(”%s\n”,b);
}
【分析】首先搞清楚数据定义语句中数组a和指针变量p1和p2的初值。
程序的第1条语句j是do-while语句。
控制该循环的条件是“*p1=‘\0'”,即当前指针变量p1指向的字符不是字符串结束标记,则进行循环。
考虑到循环体中有p1++,显然这个循环是利用指针变量p1来依次处理存放在数组a中的字符串中每个字符的标准程序段。
现在来看循环体,循环体中前一条语句是双分支语句,其控制条件“!
(*p>='0'&&*pl<'9')”的含义是当前字符不是数字字符。
当这个条件成立时,执行三条语句:
第1条赋值语句是将p1指向的当前字符复制到p2指向的数组b中;第2条语句是修改指针变量p2(加1),使其指向后一个位置;第3条赋值语句和第1条赋值语句完全相同,即把p1指向的当前字符再次复制到p2指向的数组b的当前位置上。
显然是将
p1指向的字符复制两次到p2指向的数组b中。
这个双分支语句的条件不成立时,执行“*p2=*p1”是将当前字符复制到数组b中,仅复制1次。
循环体的第2条语句是逗号表达式构成的语句,其功能是修改pl和p2(加1),使其分别指向数组。
和数组b的后一个位置。
退出循环后执行的“*p2=*p1”是将数组a中当前字符('\0')复制到数组b中,即给数组b中增加一个字符串结束标记,以便组成字符串。
最后一条语句是输出数组b中的字符串。
综合上述分析,可以得出关于程序功能的下列结论:
将存放在数组a中的字符串复制到数组b中,复制的规则如下:
当前字符是数字字符,则该字符仅复制l次;当前字符不是数字字符,则当前字符要复制两次。
因此,很容易直接写出程序运行的输出结果。
【答案】1AA2BB3CC
15阅读下列程序,写出程序运行的输出结果。
main()
{intx[10]={1,7,4,3,5},*p,*q,i;
for(p=q=x,1=0;i<10;i++,p++)
if(*q<*p)q=p;
printf(”%d\n”,q-x);
}
【分析】首先分析数据定义语句中数组x各个元素的初值,依次为1、7、4、3.5、0、…、0。
下面用记录各个变量值的方式来获得最终输出结果,记录如下:
p指向x[0],q指向x[0],i=0,条件“i<10”满足,进入循环体
第1次执行循环体:
*q=1,*p=1,条件“*q<*p”不成立,不执行q=p;执行i++,i= 1;执行p++,p指向x1],继续循环。
第2次执行循环体:
*q=1,*p=7,条件“*q<*p”成立,执行q=P,q指向x[1],执行i++,i=2;执行p++,p指向x[2],继续循环。
第3次执行循环体:
*q=7,*p=4,条件“*q<*p”不成立,不执行q=p;执行i++,i=3;执行p++,p指向x[3],继续循环。
第4次执行循环体:
*q=7,*p=3,条件“*q<*p”不成立,不执行q=p;执行i++,i=4;执行p++,p指向x[4],继续循环。
第5次执行循环体:
*q=7,*p=5,条件“*q<*p”不成立,不执行q=p;执行i++,i=5;执行p++,p指向x[5],继续循环。
第6次执行循环体:
*q=7,*p=0,条件“*q<*p”不成立,不执行q=p;执行i++,i=6;执行p++,p指向x[6],继续循环。
第7次执行循环体:
*q=7,*p=0,条件“*q<*p”不成立,不执行q=p;执行i++,i=7;执行p++,p指向x[7],继续循环。
第10次执行循环体:
*q=7,*p=0,条件“*q<*p”不成立,不执行q=p;执行i++,i=10;执行p++,p指向x[10]。
此时,控制循环的条件“i<10”不成立,退出循环。
执行输出语句,输出结果是q-x,由于指针变量q指向x[1],而x是数组首地址,代表数组元素x[0]的地址,所以q-x的值是整数1。
注意,本程序输出的实际上是教组x中最大值的下标。
【答案】1
16阅读下列程序,写出程序的主要功能。
#include”string.h”
main()
{chars[5][81],*pl[5],**p2,**p3;
inti;
for(i=0;i<5;i++)
{p1[i]=&s[i][0];
gets(p1[i]);
}
for(p3=p2=p1,i=0;i<5;i++,p2++)
if(strcmp(*p3,*p2)<0)p3=p2;
puts(*p3);
}
【分析】从数据定义语句可知,定义了一个二维字符型数组s和一个一级指针数组p1、两个二级指针变量p2、p3。
接下来的单重次数型循环执行5次,循环体中的第1条语句是将二维数组中的第i行首地址存入指针数组元素p1[i]中,第2条语句是输入一个字符串存入p[i]所指向的字符数组中第i个一维数组中。
也就是说,输入的5个数组存放在二维数组s的5行中,同时,指针数组p1的5个元素分别指向这5个字符串。
第2个循环语句也是循环5次的次数型循环。
循环的开始,先让二级指针变量p2和p3都指向一级指针数组首地址,即p2指向pl[0](注意*p2就是pl[0]),p3指向p1[0](注意*p3就是pl[0])。
循环体中利用函数strcmp()来比较*p2(第1次循环时*p2等于p1[0])和*p3(第1次循环时等于pl【0])指向的字符串的大小。
如果*p3指向的字符串比*p2指向的字符串小,则将p2存入p3中保存。
这个工作显然是用p3来保存5个字符串中最大字符串的地址。
最后的输出语句是输出*p3所指向的字符串。
综上所述,本程序的功能很容易总结出来。
分析本程序时,要注意p2和p3是二级指针变量,它们的初值等于一级指针数组p1的数组名,即这两个二级指针变量是指向一级指针数组元素pl[0]的。
此时,*p2和*p3都等于pl[0],而pl[0]是指针数组元素,其中存放的地址是字符型二维数组s中第0行第0列元素的地址,即s[0][0]的地址。
如果当作字符率来理解的话,p1[0]是指向从s[0][0]开始存放的字符串。
【答案】输入5个字符串,输出其中最大的字符串。
17编一个程序,取出一个字符串的左边n个字符组成新的字符率并输出。
原字符率及n从键盘输入。
本题要求用指向字符的指针来处理字符率中的字符。
【分析】取出某个字符串左边n个字符的算法是一个次数型循环结构,可以使用for循环来实现次数型循环结构,用指针变量来处理具体的单个字符。
【答案】#include"string.h"
main()
{chara[l00],b[100],*p_a=a,*p_b=b;
intn,i;
gets(p_a);
scanf("%d",&n);
for(i=0;i<n;i++)
*(p_b+i)=*(p_a+i);
*(p_b+i)='\0';
puts(p_b);
}
18编一个程序,从键盘上输入一串符号(以回车换行键为结束),将其以字符率形式存入一维字符型数组,然后再输出该字符型数组中的字符串。
本题要求用指向字符的指针来处理字符型数组中的字符。
【分析】本程序的结构可以这样来设计,输入一个字符,如果是回车换行符,则结束输入,否则
存入某字符型数组。
反复进行直到输入的字符是回车换行符,这段程序是标准的当型循环结构。
输入结束后,在字符数组的当前位置上(最后一个有效字符之后)置一个字符串结束标记。
【答案】main()
{chars[100],*p=s,ch;
scanf("%c",&ch);
while(ch!
='\n')
{*p=ch;
p++;
scanf("%c",&ch);
}
*p='\0';
p=s;
printf("%s\n”,p);
}
指针与指针变量
5.1 指针和指针变量
指针是程序设计语言的一个重要概念。
指针在C程序中有以下多方面的作用:
(1)利用指针能间接引用它所指的对象。
(2)利用各种类型的指针形式参数,能使函数增加描述能力。
(3)指针与数组结合,使引用数组元素的形式更加多样、访问数组元素的手段更加灵活。
(4)指针能用来描述数据和数据之间的关系,以便构造复杂的数据结构。
当一个数据A要关联另一个数据B时,在数据A中增加一个指向数据B的指针就可实现数据A关联数据B。
结合系统提供的动态分配存储设施,又能构造出各种动态数据结构。
1.指针的基本概念
为了区别内存的不同位置,内存被分成字节,内存的全部字节顺序地赋予一个称为地址的编号。
程序中的变量将在内存中占据一定的内存字节,在这些字节中存储的数据信息称为变量的内容。
一个变量占用连续的若干个内存字节时,最前面的一个字节的地址就作为该变量的地址。
指针就是内存地址,是变量的地址,或函数的入口地址。
变量的地址在程序执行时,起着非常重要的作用。
当计算机在计算含有变量的表达式时,计算机按变量的地址取出其内容,并按变量的地址将计算结果存入到变量占据的内存中。
如代码:
intx=l;
x=x+2;
其中语句“x=x+2;”中
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C语言课件 指针知识点与例题剖析 语言 课件 指针 知识点 例题 剖析