连变量的储存机制都没理解怎么能算是合格的软件工程师

连变量的储存机制都没理解怎么能算是合格的软件工程师,第1张

变量的储存机制都没理解怎么能算是合格的软件工程师

变量的储存机制
  • C语言中变量名和地址的关系探讨
    • 变量名不占空间
      • 变量
      • 变量名
  • 变量名不是内存地址,其他名都是地址吗
  • 定义int a;赋值a=5;时发生了什么
  • a=a+1执行过程
    • 汇编指令的概念
    • a=a+1的完整执行过程
  • 最后

C语言中变量名和地址的关系探讨 变量名不占空间 变量

用来标识(identify)一块内存区域,这块区域的值一般是可以更改的,这就是它“变”的由来,但是我们可以通过使用如const等一些修饰符号来限定这一内存区域的 *** 作特性(characteristic),即变量的 *** 作特性。用const修饰的使变量不能更改的就和常量一样的变量叫做常变量。

变量名

是一个标识符(identifier),用来指代一块内存区域,即变量,使用变量使我们 *** 作内存以区域(area),以块(block)为单位,提高了方便性。

你的机器代码中,是不会出现变量名的;变量名是给我们程序员 *** 作内存来使用的。想想在汇编年代,没有变量名,我们 *** 作内存,都是用地址来直接 *** 作的,还要控制区域大小;当然汇编语言已经有了简单的变量。

对于编译器,它会搜集我们的变量名,比如我们定义了一个全局的int a,那么编译器都为我们做了什么呢? 它会为程序预留4个字节的空间(假设在32位平台),并把我们的变量名“a”保存进符号表(参考编译原理的语义分析和符号表),并用这个符号表的索引对应实际的空间。如果下面出现b = a,那么它就会根据符号表找到变量的真正的物理位置,取得它的值,赋给b。这是写编译器需要做的,我们需要建立符号表。但是实际在汇编层次上, *** 作的都是地址而已,不存在任何名称了。

变量名不是内存地址,其他名都是地址吗

所谓的其他名无非是函数名、标识符常量名、指针名、数组名、结构名、类名等等。比如指针名、数组名、函数名就是地址,它们分别表示指针所指向元素的地址、数组的首地址和函数的入口地址。

变量名虽然不直接表示地址,但可用取地址符号&来获得它所代表的变量的存放地址。因为在定义变量的同时会分配给它相应的空间。

但类和结构只有事例化时才为它分配空间,从而不能用取地址符号&来获得类名或结构名的地址。变量名是用来标识某个内存块的

指针变量呢本身也是一个变量名,只不过它标识的那块内存存放的是一个地址值,变量是地址的别名。

定义int a;赋值a=5;时发生了什么

定义int a时,编译器分配4个字节内存,并命名该4个字节的空间名字为a(即变量名),当用到变量名a时,就是在使用那4个字节的内存空间。

5是一个常数,,在程序编译时存放在代码的常量区存放着它的值(就是5),当执行a=5时,程序将5这个常量拷贝到a所在的4个字节空间中,就完成了赋值 *** 作,a是我们对那个整形变量的4个字节取的"名字",是我们人为给的,实际上计算机并不存储a这个名字,只是我们编程时给那4个字节内存取个名字好用。

实际上程序在编译时,所有的a都转换为了那个地址空间了,编译成机器代码后,没有a这个说法了,a这个名字只存在于我们编写的代码中,5不是被随机分配的,而总是位于程序的数据段中,可能在不同的机器上在数据段中的位置可能不一致,它的地址其实不能以我们常用到的内存地址来理解,涉及到"计算机寻址方式"的问题,这里不多解释。

a=a+1执行过程

通过图片我们进一步理解

对于a=a+1这条程序语句需要分解为三步:
1、把变量a读取到某一个寄存器R存储
2、CPU对寄存器R的值进行计算
3、计算完成后将值存回内存

分解“a=a+1”的执行步骤:
第一步,CPU从地址300处读取第一条语句,CPU执行“读取a到R"语句,就会从地址1000出将a的值读到寄存器R中。
第二步,CPU从地址301处读取第二条语句,执行"R+1"语句,CPU会对R执行加1的 *** 作
第三步,CPU从地址302出读取第三条语句,执行"将R存回a"语句,把寄存器R中变量a的值存回到内存中地址1000处。

汇编指令的概念

汇编指令由 *** 作码和 *** 作数组成, *** 作码是指令执行的基本动作,在load R1,(address)中,load是 *** 作码,其后的寄存器R1和(address)都是 *** 作数
(1)"读取a到R" *** 作-load指令:
load执行用来表示"CPU将内存中的a读取到寄存器R中"的 *** 作。load指令需要有两个 *** 作数。格式:load R1,(address),address是内存地址,(address)表示这个地址内存的值。例load R1,(1000)表示将地址1000处的变量值读取到寄存器R1中。

(2)"R赋值" *** 作-mov指令:
格式:mov R1,constant mov用来将一个数赋给寄存器,mov指令有两个 *** 作数前一个是寄存器,后一个是十六进制常数。例mov R1,0Ah表示将0Ah(十进制10)赋给寄存器R1。mov R2,R1表示将寄存器R1的值赋值给R2。

(3)"R加1" *** 作-add指令
格式:add R2,R1,constant 表示将R2=R1+constant。例add R2,R1,01h表示将寄存器R1中的值加1后将结果存到R2。例add R1,R1,R2表示将R1与R2的值相加将和存回R1。

(4)减法指令-sub
格式:sub R2,R1,constant 表示R2=R1-constant。例sub R3,R1,R2表示R3=R1-R2

(5)左移位指令shiftl
格式shiftl R2,R1,constant 表示R1寄存器的值左移constant位然后将值存入R2,左移一位就相当于乘以2,左移两位就相当与乘以4。例:shiftl R2,R1,05h表示R2 = R1 * 2的5次方

(6)右移位指令shiftr

(7)"将R存回a" *** 作-store指令
格式:store (address),R1 程序语句中的存回表示将寄存器R中的值存回到内存中。address是内存地址,(address)是要存回的值,R1是寄存器。例:store (500),R1表示将寄存器R1中的值存入到内存地址500处

a=a+1的完整执行过程

首先用汇编指令表示一下这个过程(a = 10;a = a + 1)

mov R1,0Ah
store (1000),R1
load R1,(1000)
add R1,R1,01h
store (1000),R1

具体执行过程:

(1)CPU从地址301处开始执行,PC的值为301,CPU从地址301处读取mov指令到IR,解读并执行mov指令,给寄存器R1中的变量赋初值10,然后PC加1,指向下一条汇编指令

(2)PC值为302,CPU从地址302处读取store指令到IR,解读并执行store指令,将寄存器R1中的变量a的值存到内存地址1000处,然后PC加1指向下一条汇编指令。

(3)PC的值为304,CPU从地址304处读取add指令到IR,解读并执行add指令,将寄存器R1中变量a的值加1,并将结果再存回寄存器R1,然后PC加1,指向下一条汇编指令。

最后

通过上文的学习,你就能更好的理解下面的几篇文章了
推荐阅读:
指针变量的传值、传址和传引用
万物皆“指针”

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5691440.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存