SCANF函数到底什么时候才用&
(一)什么时候要使用&
1、基本数据类型:
对于基本数据类型(如整数、浮点数、字符等),都要使用&(取地址符)
2、数组
当取地址的对象为数组时不用使用&(取地址符)
3、指针变量
指针变量也需要写取地址符号&
(二)数组知识(可跳过)
首先让简单回顾一下数组的知识:
1、数组的概念
一堆同类型元素的集合
2、数组的特点
①是相同类型的元素
②具有固定大小
③连续存储
④使用索引(即下标)访问元素
3、数组的地址
数组的地址指的是数组在内存中的起始位置的地址,也就是数组的第一个元素的地址。
(三)进入正题
以 int add[10]={1,2,3}作为例子
1、数组为什么不需要加 &?
数组的地址指的是数组在内存中的起始位置的地址,也就是数组的第一个元素的地址。而在C语言中将数组名解释为指向数组首元素的指针。也就是说数组名(add)其实就已经包含了地址的信息,不需要额外再用&(取地址符)获取该数组的地址信息。
2、那&add又代表什么意思呢?
代表的是数组的地址的地址吗?看起来是这样的,但这个概念不适合C语言中的数组。实际上,它有自己的含义,取地址符+数组名(&add)表示的是整个数组(add)的地址。
而在C语言中我们将数组的起始位置看作整个数组的地址。为什么呢,因为我们数组是在内存空间是连续存储的,我们可以通过数组长度知道数组的结束位置,所以我们知道了它的首元素的地址就相当于知道了它整个数组的地址(像是排队,你看到排头,你就知道这个队伍的位置了,你可以顺着队伍往后走,从而得知其他人的位置),此时我们一般用add的形式表示它的地址。因此我们在一般情况都会认为整个数组的地址就是首元素地址,但是真正意义上它不是整个数组的地址,我们只是看作而已。那么其实&add则是回归了它真正的含义--整个数组的地址(指从头到尾整个的地址)。
3、为什么一定要add而不是&add
① 核心原因:此时要引入scanf函数的知识了,核心是scanf函数一个参数只能接收一个指针。很明显我们在接收数组地址的时候,我们只会写一个占位符 [1],一个占位符自然对应要传一个参数[2],而scanf需要的参数类型是指针[3],也就是说,一个%d(占位符)对应一个地址,(总的来说就是一个占位符对应一个参数,而一个参数只能接收一个指针。)因此,我们在传数组地址的时候,我们只能传一个地址,那就是只能add(数组名)的形式传首字符的地址,&add的形式是传整个数组的地址(整个数组不止一个地址),因此我们不能写成&add这种形式。
②次要原因:&add的形式是传整个数组的地址。然而我们并不知道数组结束的信息,当然我们可以通过首字符后移的方式,直到达到数组的长度,从而得知数组得结束位置,但是!scanf函数只是接收地址,不知道数组的长度,数组结束信息也就无从谈起,也就是说我们无法得知整个数组的地址。理论上,scanf函数能知道数组长度,那么我们可以写成&add的形式,但是由于只能传递一个指针,因此scanf函数关注的还是首地址。
[1]占位符,举例讲就是%d,%f之类的,不作详细解释
[2]参数?重点不在这,在这个例子就是后面的add
[3]指针(指针变量)是存储地址的变量,但是本质上scanf函数只是通过指针来获取需要的地址,因此我们没有传递指针变量,只是传递地址也可以(实在不明白,大家可以笼统的认为指针就是地址)
当然啊,相信大家还有一些疑问,以下作个简单解答。
4、只传了首元素指针,怎么存整个数组呢?
我们都知道一个元素对应一个指针,现在只传了一个首元素指针,怎么存后面的元素呢?还是要引入scanf函数的知识,scanf函数会以数组的首元素指针为初始地址,不断读取字符,同时每次存储完一个字符,指针会自动后移,指向下一个要存储的位置。(数组的存续空间是连续的,指针后移的位置就是首元素后下一个元素的地址,以此类推)直到遇到空白符、换行符或者达到指定输入长度。
5、scanf函数不知道数组长度,那它怎么确定数组什么时候满呢?
相信爱思考的小伙伴都发现了,既然scanf函数不知道数组长度(不知道数组结束位置),那它怎么知道什么时候停呢,万一用户输入的内容超出了数组长度怎么办?没错,这里就涉及到缓冲区溢出[4]的问题,可能会导致程序出错。因此我们可以采用格式字符串中指定最大字符数来实现,像这样我们限定了最大字符为10,scanf函数接收10元素后就会停止了。当然更优解是使用fgets函数。
[4]不作详细解释,此例中指的是用户输入的内容过多,本来10给个元素就够了,但是scanf函数不知道什么时候结束,因此多读了几个元素
(四)结语
可能还是有点乱乱的,总的来说。一般情况,我们把数组名代表的首元素指针看作(只是看作)整个数组的地址,因为我们可以通过数组长度计算得出数组实际的整个的地址。在scanf里数组名在此代表的也是首元素自己的指针,我们仍然把数组名的首元素指针看作整个数组的地址,不一样的是scsanf函数无法通过数组长度计算得出数组实际的整个的地址,因此实际上我们并不知道它的整个地址。因此我们不会使用&add的形式来获取数组地址。使用add形式就已经包含地址信息了。
(五)作者念叨
好了,本期博客就到这里吧,希望对大家有帮助,大家如果还有什么疑问,欢迎到别的博主那里寻找答案哦 ~
博主很佛,只在发博客的一瞬间在线,其他时间都在潜水。
有些概念没有多做解释,有些同学可能基础没写完,可能不理解,望原谅。大家可以自行去了解。溜走~~