一、选择题(在下列各题的A)、B)、C)、D)四个选项中,只有一个选项是正确的,请将正确选项填涂在答题卡相应位置上。)10.1b 下列关于指针变量赋空值的说法错误的是
A)当赋空值的时候,变量指向地址为0的存储单元
B)赋值语句可以表达为变量名=′\0′;
C)赋值语句可以表达为变量名=0;
D)一个指针变量可以被赋空值
A)求字符串的长度 B)比较两个字符串的大小
10.3b 下面程序段中,输出*的个数是
10.4b 下列程序是用来判断数组中特定元素的位置所在。如果输入如下整数:
若从键盘输入:abc def,则输出结果是
程序运行后的输出结果是
A)指向char变量的指针
B)指向指针的char变量
10.8b 阅读下面程序,执行后的结果为
10.9b 阅读下面程序,在程序执行后的结果为
10.10b 阅读下列程序,则执行后的结果为
则程序段执行后的结果为
表示数组元素s[i]的表达式不正确的是
10.15b 阅读如下程序段,这个程序在编译的时候会有一个警告,下列关于这个警告叙述正确的是
A)指针k没有指向任何对象而成为“无向指针”,所以这里会产生警告
B)return语句不应该有括号,所以在这里会有警告
C)return语句的返回值类型与指针k的基类型不一致,这里会产生警告
D)数组赋值的时候没有把数组全部都赋初值,所以在这里会有警告
10.18b 阅读下面程序,则执行后输出的结果为
10.19b 阅读下面程序,则执行后的结果为
10.21b 阅读如下程序段,则执行后的结果为
10.24b 阅读下面程序,则程序的输出结果为
二、填空题(请将每一个空的正确答案写在答题卡相应序号后。)10.26b 设有以下定义和语句,则*(*(p+2)+1)的值为【1b】。
10.27b 以下函数用来在w数组中插入x。n所指向的存储单元中存放w数组中字符个数。数组w中的字符已按从小到大的顺序排列,插入后数组w中的字符仍有序。请填空。
10.28b 以下程序中,select 函数的功能是:在N行M列的二维数组中,选出一个最大值作为函数值返回,并通过形参传回此最大值所在的行下标。请填空。
10.30b 下面的程序实现的是指针p所指向的地址的n个数中,求出最大的和最小的数据,请填空。
10.32b 下面程序的功能是:对字符串从小到大进行排序并输出,请填空。
10.33b 下面程序段的功能是:从键盘上输入两个字符串,对两个字符串分别排序;然后将它们合并,合并后的字符串按ASCII码值从小到大排序,并删去相同的字符。请填空。
C语言中的指针是C语言的精髓,也是C语言的重难点之一。
然而,很少有教程能把指针讲的初学者能听懂,还不会引起歧义。
本文章会尝试做到这一点,如有错误,请指出。
我们先抛开指针不谈,来讲一个小故事:
一天,小L准备去找小S玩。但是小L不知道小S的家住在哪里,正当他着急的时候,他看到了一个路牌,上面写着:小S的家在神仙小区403
哦,真的是要素过多。为什么这么说?
搞懂了上面,我们再来聊聊&
&
这个符号我们一个不陌生,你最初用到应该是在:scanf("%d",&a)
里边。
&
叫做取址符,用来获取一个变量/常量的地址。
那么我们为什么要在scanf
里边用&
,不在printf
里边用呢?
一开始我也很疑惑,后来我看到了这个例子:
你是一个新生,你要进教室。
但是你并不知道教室在哪里,这个时候你需要教室的地址。
由于你已经在教室里了,你就不需要获取教室的地址就可以出去了。
一定要记住:指针就是个变量!
指针就是个变量!他储存的是地址!他自己也有地址!
指针就是个变量!他储存的是地址!他自己也有地址!
指针就是个变量!他储存的是地址!他自己也有地址!
为什么这么说?我们从指针的定义开始:
也就是说,指针的定义大概是这样的:
这么写当然没问题,但是对于初学者来说,有两个问题:
*p
当做是指针名
*p
和取值时出现的*p
弄混
指针他有没有值?有!我们会在下一节给他赋值。
既然他的定义方式和变量一样,他也有值,他为什么不是变量呢?
与指针相关的符号有两个,一个是&
,一个是*
。
&
我们上面讲过,他是来取地址的。举个例子:
%p
用来输出地址,当然,你也可以写成%d
或者%x
。先不管这个,我们来看看他会输出什么:
那么也就是说,变量a
和b
的地址是FE1C
和FE18
那么我们怎么把这个地址给指针呢?很简单:p = &a;
,举个例子:
指针p自身的地址:FE10
指针p指向的地址:FE1C
你发现了吗?如果我们有p = &a;
,我们发现:直接输出p会输出a的地址,输出&p会输出p的地址(这就是为什么我一再强调p是个变量,他有自己的地址,正如路牌上有地址,路牌自身也有个地址一样)。
int*
,那么你只能指向int
类型;如果是double*
类型,只能指向double
类型,以此类推
当然,void*
类型的指针可以转化为任何一种不同的指针类型(如int*
,double*
等等)
那么,我们来聊聊第二个符号*
*
有两个用法。第一个在定义指针时用到,第二个则是取值,什么意思?看下面这个例子:
指针p自身的地址:FE10
指针p指向的地址:FE1C
指针p指向的地址的值:10
哈,我们得到了a的值!
也就是说,当我们有p = &a
,我们可以用*p
得到a的值。
那能不能操作呢?当然可以。
我们可以把*p
当做a的值,那么,我们尝试如下代码:
指针p指向的地址的值:10
指针p指向的地址的值:13
指针p指向的地址的值:16
指针p指向的地址的值:13
指针p指向的地址的值:117
指针p指向的地址的值:39
指针p指向的地址的值:0
棒极了!我们可以用指针来操作变量了。
那么,我们要这个干什么用呢?请看下一节:实现交换函数
交换函数是指针必学的一个东西。一般的交换我们会这么写:
那么我们把它塞到函数里边:
好,我们满怀信心的调用他:
于是乎,你得到了这个输出:
啊啊啊啊啊啊啊啊,为什么不行!!!
问题就在你的swap函数,我们来看看他们做了些啥:
各位同学,函数体内有任何一点谈到了x和y吗?
所谓的交换,交换的到底是a和b,还是x和y?
我相信你这时候你恍然大悟了,我们一直在交换a和b,并没有操作x和y
那么我们怎么操作?指针!
因为x和y在整个程序中的地址一定是不变的,那么我们通过上一节的指针运算可以得到,我们能够经过指针操作变量的值。
那么,我们改进一下这个函数
我们再来试试,然后你就会得到报错信息。
我想,你是这么用的:swap(x,y)
。
问题就在这里,我们看看swap需要怎样的两个变量?int*
和int*
类型。
怎么办?我告诉你一个小秘密:
任何一个变量加上&,此时就相当于在原本的类型加上了*
char*这个神奇的类型可以表示个字符串,举个例子:
请注意:输入和输出字符串的时候,都不能带上*
和&
。
你可以用string.h
中的函数来进行操作
当你没有让p指向某个地方的时候,你还把他用了!这个时候就会产生野指针。
第一种是指向不可访问(操作系统不允许访问的敏感地址,譬如内核空间)的地址,结果是触发段错误,这种算是最好的情况了;
第二种是指向一个可用的、而且没什么特别意义的空间(譬如我们曾经使用过但是已经不用的栈空间或堆空间),这时候程序运行不会出错,也不会对当前程序造成损害,这种情况下会掩盖你的程序错误,让你以为程序没问题,其实是有问题的;
第三种情况就是指向了一个可用的空间,而且这个空间其实在程序中正在被使用(譬如说是程序的一个变量x),那么野指针的解引用就会刚好修改这个变量x的值,导致这个变量莫名其妙的被改变,程序出现离奇的错误。一般最终都会导致程序崩溃,或者数据被损害。这种危害是最大的。
不论如何,我们都不希望看到这些发生。
于是,养成好习惯:变量先赋值。
指针你可以这么做:int *p =NULL;
让指针指向空
不论如何,他总算有个值了。
本文干货全部在这里了:
数据类型+*
,他的值是一个地址,他自身也有地址
&
和*
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。