C语言scanf()函数使用时括号里的变量前面为什么有一个&符号

文章介绍了C语言中scanf函数的作用,特别是&符号的含义,它用于取变量地址以便于函数修改变量值。文中通过实例解释了如何使用scanf从键盘输入数据到变量,并提到了其他输入函数如getchar()和gets()。此外,还简述了内存地址和虚拟地址的概念。

我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来重点说一说scanf()函数,还要专门说一下C语言scanf()函数使用时括号里为什么有一个&符号,这在很多C语言的书上从来不解释。但是我觉得不解释对后面的理解不好。

程序是要和硬件交互的,有输出必然也有输入,现在我们讲解如何从键盘输入数据。在C语言中,有多个函数可以从键盘获得用户输入:

scanf():可以输入多种类型的数据。

getchar()、getche():用于输入单个字符。

gets():获取一行数据,并作为字符串处理。

scanf() 是最常用的输入函数,但它不能完全取代其他函数。

#include <stdio.h>
int main()
{
    int a = 0, b = 0, c = 0, d = 0;
    scanf("%d", &a);  //输入整数并赋值给a
    scanf("%d", &b);  //输入整数并赋值给b
    printf("a+b=%d\n", a+b);  //计算a+b的值
    scanf("%d %d", &c, &d);  //输入两个整数并分别赋值给c和d
    printf("c*d=%d\n", c*d);  //计算c*d的值
    return 0;
}

运行结果:

10↙

20↙

a+b=30

10 20↙

c*d=200

对于所有变量都有格式控制字符串,都有变量列表。我们注意到,scanf 的变量前要带一个&符号。&称为取地址符,也就是获取变量在内存中的地址。

数据是以二进制的形式保存在内存中的,字节(Byte)是最小的可操作单位。为了便于管理,我们给每个字节分配了一个编号,使用该字节时,只要知道编号就可以,就像每个职工都有工号,自由讨论时,主管会随机抽取工号来让职工回答问题。字节的编号是有顺序的,从 0 开始,接下来是 1、2、3……

下图是 4G 内存中每个字节的编号(以十六进制表示):

这个编号,就叫做地址(Address)。int a;会在内存中分配四个字节的空间,我们将第一个字节的地址称为变量 a 的地址,也就是&a的值。对于前面讲到的整数、浮点数、字符,都要使用 & 获取它们的地址,scanf 会根据地址把读取到的数据写入内存。

下面把变量的地址输出看一下:

#include <stdio.h>
int main()
{
    int a='A';
    int b=20;
    int c=500;
    printf("&a=%p, &b=%p, &c=%p\n", &a, &b, &c);
   
    return 0;
}

输出结果就是三个地址。%p是一个格式控制符,它表示以十六进制的形式(带小写的前缀)输出数据的地址。如果写作%P,那么十六进制的前缀也将变成大写形式。

注意:上面输出结果里看到的地址都是虚拟地址,并不是数据在物理内存中的地址。虚拟地址是现代计算机操作系统因内存管理的需要才做出来的一种机制,以前的旧操作系统没有这个机制。

现在就我们本文开始时提出的问题进行回答,C语言scanf()函数使用时括号里为什么有一个&符号,&符号究竟是做什么用的?

我们的结论是:

在程序中经常用到的scanf()函数,是需要取得变量的地址用以修改变量的值,如下代码所示:

scanf("%d", &a);

此代码通过“&”取地址运算符获取变量a的地址,然后使用终端输入设备改变变量a的值。

所以说,这个变量前的位置必须有一个&符号。只有理解了以上,才能真正明白为什么scanf的代码要这么写。

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。

&lt;think&gt;用户的问题中提到了一个明显的错误:在scanf使用了$符号(用户写的是$,但实际应该是&amp;)。用户可能混淆了$和&amp;的用法。 用户的问题:为什么scanf括号面的a和b前面要有$(实际应该是&amp;),printf括号面不用,这是拿来干嘛的 需要纠正用户:在C语言中,scanf需要的是变量的地址,所以使用取地址运算符&amp;(ampersand),而不是$(dollar sign)。用户可能打字错误或理解有误。 因此,回答应该包括: 1. 指出正确符号&amp;,不是$。 2. 解释&amp;的作用:取地址运算符,用于获取变量的内存地址,以便scanf输入存储到该地址。 3. 解释为什么printf不需要:因为printf只需要变量,所以直接传递变量即可(传递的是变量,而不是地址)。 同,按照规则,在回答后提出3-5个相关问题,以&ldquo;&sect;&sect;相关问题&sect;&sect;&rdquo;开头。 注意:用户提供的代码示例中,scanf使用的是&amp;a, &amp;b,并没有$,所以可能是用户描述打错了字。 回答结构: - 先纠正符号错误 - 解释&amp;的作用和必要性 - 对比printf的参数传递方式 - 给出示例代码说明 - 最后输出相关问题&lt;/think&gt;您的观察很准确,这涉及到C语言中指针和内存地址的核心概念。以下是详细解释: ### 关键区别:`&amp;`符号的作用 1. **`scanf`需要变量的内存地址**: - `scanf(&quot;%d&quot;, &amp;a)` 中的 `&amp;a` 表示&quot;变量a的内存地址&quot; - 因为`scanf`需要知道将输入存储到内存的哪个位置 - 相当于告诉函数&quot;请把读取到的数字存放到a所在的内存空间&quot; 2. **`printf`只需要变量**: - `printf(&quot;%d&quot;, a)` 直接传递变量a的 - 因为`printf`只需要获取进行显示,不需要修改原始变量 ### 内存操作示意图: ``` 变量a: [ 内存地址0x1000 ] &rarr; 存储 0 变量b: [ 内存地址0x1004 ] &rarr; 存储 0 scanf(&quot;%d%d&quot;, &amp;a, &amp;b) 实际接收: &amp;a = 0x1000 &amp;b = 0x1004 输入&quot;2 3&quot;后: a = 2 (地址0x1000的变为2) b = 3 (地址0x1004的变为3) printf(&quot;%d%d&quot;, a, b) 实际输出: 直接读取a的2和b的3 ``` ### 为什么这样设计? 1. **输入需要修改原变量**: - `scanf`必须能修改内存中的 - 在C语言中,函数要修改外部变量,必须通过指针传递地址 2. **输出只需读取**: - `printf`只需读取进行显示,不需要修改原变量 - 直接传递副本更高效安全 ### 错误示例分析: ```c int x = 0; scanf(&quot;%d&quot;, x); // 错误!缺少&amp; ``` 这将导致: 1. `scanf`尝试把输入写入内存地址0(x的) 2. 由于0是非法地址,程序崩溃或行为未定义 ### 正确用法对比: | 函数 | 目的 | 参数要求 | 示例 | |---------|------------|---------------|---------------| | `scanf` | 输入数据 | 变量地址(&amp;) | `scanf(&quot;%d&quot;, &amp;num)` | | `printf`| 输出数据 | 变量 | `printf(&quot;%d&quot;, num)` |
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值