You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言指针疑问:scanf传址、赋值及字符串输入逻辑困惑

C语言指针与底层架构的对应解释

问题1:为何scanf("%d", &c)可行,c = &p却报错?

先看代码核心差异:

  • 第一个片段中,&c是取变量c的内存地址,类型为int*(指向int的指针),而scanf的%d格式符要求传入一个能存储int值的内存地址——两者类型完全匹配。
  • 第二个片段中,c是int类型变量,用于存储整数数值;&p是int*类型,存储的是变量p的内存地址。C语言的强类型系统不允许直接把地址(指针类型)赋值给普通整数变量,编译阶段就会触发类型不匹配错误。

结合CDU(控制解码单元)、MAR(内存地址寄存器)、*MDR(内存数据寄存器)*的底层逻辑:
当CPU执行scanf("%d", &c)时:

  1. CDU解析scanf调用指令,识别到需要向指定内存地址写入数据。
  2. &c的数值(即c的内存地址)被加载到MAR,MAR负责通过地址总线传递要访问的内存位置。
  3. 用户输入的整数通过输入设备传入MDR,MDR负责通过数据总线暂存要写入内存的数据。
  4. CDU发出一系列微指令,控制将MDR中的数据写入MAR指向的内存单元(也就是c对应的内存位置),完成赋值操作。

而执行c = &p时:
CDU在编译阶段(或汇编阶段)就会发现源操作数是指针类型(地址值),目标操作数是int类型(数值),两者的位宽和语义不匹配——CPU的微指令序列没有设计这种跨类型的直接赋值逻辑,因此编译直接报错,根本不会生成可执行的机器码。

问题2:为何字符数组输入无需使用&?

你的示例中char val[2]; scanf("%c", val);能正常运行,核心原因是:数组名val在作为函数参数时,会被隐式转换为指向数组首元素的指针,也就是val等价于&val[0]——本质上还是传入了内存地址,完全符合scanf对参数的要求。

底层架构层面的解释:

  1. 当val作为参数传入scanf时,CDU解析到这个参数是数组名,自动将其转换为数组首元素的内存地址,加载到MAR中。
  2. 用户输入的字符通过输入设备传入MDR,CDU执行微指令,将MDR中的字符数据写入MAR指向的内存单元(即val[0]的位置)。
  3. 如果是普通字符变量char c;,必须用&c取地址——因为变量名c直接关联的是它存储的数值,而非内存地址;而数组名本身就是内存块的起始地址标识,无需额外取地址操作。

注意:如果是用%s读取字符串(比如scanf("%s", val);),原理完全一致——val作为首元素指针传入,scanf会把输入的字符序列依次写入从该地址开始的连续内存单元,直到遇到终止符\0。

内容的提问来源于stack exchange,提问作者Bitwoded S.Demissie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 07:47:23