取地址操作符触发的对编程语言数据传输/读写哲思

本文解释了C语言中取地址运算符“&”的概念及其使用场景,详细介绍了变量存储空间与取地址符的关系,帮助读者理解输入输出操作。

C语言取地址操作符触发的对编程语言数据传输/读写哲思

2015-04-14  青岛  张俊浩

2025-11 北京 修正之前混淆读写认知,同时用更贴近底层硬件但又简单美的方式表述

今天在论坛贴吧看到关于C语言操作符/取地址符"&"的问题,因为之前自己学C语言时也遇到这个问题,触发了许多关于编程语言、计算机底层硬件机制的思考,就整理一下思路回帖,也顺便整理成一篇博客~

问题如下:

int a;
scanf("%d",&a);
我们老师讲,&是取地址符,但是我就奇怪,为什么叫取地址?地址不是形容一个事物在哪吗?
我们明明是想知道a是多少,而不是说它在哪,我输个10,a就是10了呀。

额,个人感觉C语言是门很"硬"的语言,因为它相对其他高级语言更接近硬件底层,而相对于机器指令汇编又跳出了繁琐的底层处理器指令编程。
无法理解"&"或者说"地址"、"取地址",是因为你站在高级(自然语言)语言的层面,而不是机器本身。任何变量都是数据,数据就会在硬件机器上有他的存储空间,存储空间有对应的位置,来方便我们操作这个存储空间,比如存储设备,内存,内存空间,内存地址。
这里我们定义了变量a,比如int a; 实际上是预留了一个存储空间,存储空间有相应的位置/地址,我们用符号"a"来指代,我们编译高级语言的时候,编译器会把我们所以对变量a的操作,转化为对相应存储空间的操作。


对一块存储空间本质上有两种操作:读、写,或者称输出、输入。读写操作本质对应着数据传输的过程:从源到目的,源=》目地。

"=" vs "f"

1.简单的数据传输过程:操作符"="

高级语言中用操作符"="表示数据的读写、传输过程,是数据的从一个存储空间向另一个存储空间传输的过程,或者说数据从源存储空间读出,写入目的存储空间。我们一般用操作符"="表示数据传输的过程,表示读出写入操作。操作符"="操作的对象:右侧为数据源,读操作的操作对象,一般称为右值,左侧为数据目的存储空间,写操作的操作对象,一般称为左值。

比如:

1.1 a = 1; //内存地址的指代符号a在操作符"="的左侧,a称为左值,是写操作的目地地址,表示是往目的地址a的存储空间写数据;这里源数据是一个立即数,立即数一般存储在指令中;本条代码指令做的数据传输/读写操作:把从指令中解码后的立即数"1"写入目的地址a对应的存储空间;

1.2 b = a; //内存地址的指代符号a在操作符=的右侧,a称为右值,是读操作的数据源;内存地址的指代符号b在操作符=的左侧,b称为左值,是写操作的目的地址;这条代码指令做的数据传输/读写操作:从源地址a所对应的存储空间读出数据,写入目的地址b所对应的存储空间。

2. 复杂的数据处理、传输过程:封装成函数::f

数据往往不只是简单的传输,从源地址存储空间读取/获得的输入数据,一般需要做一定处理之后,再写入/输出目的存储空间。

这些复杂/多样/具体的数据传输、处理过程就不能用简单的数据传输符号"="来表示,计算机编程语言把这个过程封装为f/函数/方法/算法/算子:函数接收数据,处理数据,输出处理后的数据。

或者数学式更简洁的表述:

y = f(x)

x::读::输入数据 =》f::函数::算法::处理数据 =》y::写::输出数据

或者伪代码式表述:

输出 函数 (输入) {

        算法具体实现:处理数据

}
 

2.1 函数做读出/输入操作时

把要传输的数据的源地址传递给函数即可,函数会从源地址读取数据,传递给函数处理。变量名即地址,如果想从变量名所指代的地址空间读数据传入函数,直接传变量名即可。


以printf为例:

printf("%d", a); //prinf函数的作用是从源地址/输入地址存储空间读取数据,然后往标准输出stdout输出,函数传入的数据(除了格式化字符串)是一个源存储空间的地址;变量名a即地址,从变量名a所指代的地址空间读取数据传入函数,所以直接传变量名即可。

2.2 函数做写入/输出操作时

2.2.1 y = f(x):y即函数f返回数据要写入的地址

2.2.2 或者把要写入的地址传给函数f

以本篇博客最开始讨论的函数scanf为例,关于C语言地址、取地址运算符"&"

scanf("%d",&a):

scanf函数的作用是把从标准输入stdin获得的数据格式化后写入一个目的存储空间,函数传入的数据(除了格式化字符串)是一个目地存储空间的地址;

&a作为scanf函数的输入数据,&a是什么?&a其实就是符号a所指代的内存地址,"&"操作符是为了获得存储空间地址a,把存储空间地址a传给scanf函数,让scanf函数往地址a所指向目的存储空间写数据;如果不加操作符号 "&",就会把存储空间a(这里把存储空间与存储存储空间地址简化等同)存储的数值,误当成要写入内存地址,传给scanf函数,造成的后果是scanf函数试图把从标准输获得数据往错误的地址对应的存储空间写,而非地址a指向的存储空间,近一步会触发内存越界、段错误,即便不发生错误,也非我们想要的数据正确写入的地址。

当然如果想了解=、函数数据的传递更底层的细节,需要具体到代码、硬件视角的话,需要了解栈帧,寄存器,需要了解编译过程,需要看编译后的汇编代码,ELF、机器指令,处理器硬件架构设计,梁晓晖译《汇编语言:基于Linux环境》、马朝晖译《汇编语言程序设计》、《程序员的自我修养》是不错的自我修养进阶。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值