避坑_数组转化为指针的规则

今天有人问我scanf输入字符串为什么不加&,我果断给他解释一波……
在这里插入图片描述
但是自己顺手又加上&试了一波:
在这里插入图片描述
我真的是一脸懵逼,原本还以为掌握指针了,结果被这么小的问题卡住,我想不明白,去查书、百度了一波。

贴吧(点这里去原帖)上回答是这样的(讲得真的很好):
(为了方便,我下面引用一下,原帖链接:https://tieba.baidu.com/p/6190822192)

【 我直接说吧,你这个看几次 * 就想当然说本质的方法论就是错误的。 作为现实的问题,你要知道 C 语言有个很妖的骚操作:隐式转换。
更妖孽的是,这样的转换可能大部分情况下都有,但也不是每个上下文中都有,而且前后类型的不同可以影响其它部分的程序,所以不可能看作转换前后等价。
很不巧,数组类型的表达式转换成指针值的转换就是这种情况。这种转换的主要内容是,在合适的上下文中,数组类型 T[N] 的表达式 a
会转换成指针类型 T* 的表达式 &a[0] 。 这不表示 a 就是 &a[0]
。如果已经从数组表达式转换为指针,那就是指针值,不会转换回数组类型的值。这是个单向的过程——这也是在 C 中你不能忽略这个转换的主要原因。
这样,连续的 * 之间不会总是保持其中的东西就是你写出来的直接结果。 注意到 *
的结果可能是数组或者非数组类型的值,并且如果作用在数组指针值上它的结果还是个数组左值,这个结果在合适的上下文中可能继续转换。
所以你甚至都不能保证依赖 * 的次数来推断转换了几次—— *
几次的中间结果是数组指针和中间结果是非数组指针的情况下,转换几次的情况是不一样的。
为什么要强调先清楚左值?因为事实上,左值这样指称对象同一性(identity)
要求的性质在一些地方决定是不是允许存在这个转换而能保持逻辑上说得通。(某种意义上,这是唯一能从需求角度上理解 C
的某些奇葩规则设计的合理思路。) 上面说过,不是所有上下文都存在这种转换。例如,作为 sizeof 和 &
的操作数时,这种转换就不会发生:对数组 a ,sizeof(a) 和 sizeof(&a[0]) 显然是两回事;对数组左值 a ,&a
有意义,但 &(&a[0])
是非法的。原则上这是因为,这样的操作要么要求保留(左)值原本的信息,要么直接依赖操作数是个左值这样的事实。这样的上下文习惯上称为左值上下文(lvalue
context) 。 (当然,也有通过非左值的成员访问操作 . 搞出数组非左值然后转换,不过也不是这里的情况。) 数组的值在 C
中不是一等对象(first-class object)
,如当实际参数传递以后不会保持数组值,一个理由就是普遍存在的这个转换。这导致你很难发现发生影响的情况到底是什么。 个别其它语言如 C++
和这里的表现一样,但 C++ 好歹有绑定到左值的数组引用,相对容易区分一个表达式到底是本来就是数组,还是数组转换后的指针;而且 C++
还有直接判断类型的 decltype 之类的内建操作( C 的直接操作得指望扩展);也因此 C++ 用户反而相对不容易陷入混淆。
另外,类似的破事不是数组独有的。 例如一个函数指针 fp 你可以一个劲地 ******fp下去几次都可以。于是你能认为函数指针 *
出来的东西本质就是能无限 * 的东西了? 显然这是不靠谱的。实际情况是函数指针
出来的东西在这个上下文中会转换成函数指针,每 *
一次就转回来,之后 * 的还是函数指针。 题外话,函数指针 * 出来的 function designator 不是 C
意义上的左值,不过在 C++ 中也归类为左值了。 左值到右值转换(lvalue-to-rvalue conversion)(对应 C
的左值转换 )、数组到指针值的转换(array-to-pointer conversion)
和函数到函数指针值的转换(function-to-pointer conversion) 在 C++
中都是“左值变换(LvalueTransformation) ”这个大类中(虽然其实数组到指针转换同样不要求左值操作数)。 这三种转换在 C
都有对应。即便数组转换不需要左值操作数, function designator 并非左值,这三种转换也都在 ISO C
定义何为左值的同一节中规定,并且有个共性:结果都不能保持左值。所以虽然 C
这方面字面上看不出来,但其中的“可能影响左值性和/或类型”联系仍然还算是清晰的。 】

然后查书也看到了一句话:在这里插入图片描述
还是把数组和指针混淆了,数组名应该也只是传参的时候才化为指针。

感觉自己还是好菜,难受得要死,加油吧…………

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

barbyQAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值