从编译器角度理解C++中的引用和指针

时间:2023-12-09 22:32:01

欲分析指针和引用,则要分析变量名和地址之间的关系(不管你理解还是不理解,无论你是从老师那里听到的,还是网上看到的,应该都知道两句话:1、 指针就是地址,2、引用就是给变量起个别名)

所以我们就要来分析分析变量名和地址之间的关系。这就要从编译原理中的符号表说起,我们上编译原理的时候老师就没有将那一章,所以对于符号表,我的认识比较浅显,不过应该已经能够解释地址和变量名之间的关系啦。

编译器中通常要维护一个符号表,而且这个符号表是要贯串整个编译过程的。网上盗了张图

从编译器角度理解C++中的引用和指针

如果没有学过编译原理,看不懂这张图也没有关系,只需要知道,编译器维护了一张符号表,而且这个表贯串整个编译过程就好。

这张表有什么用呢? 我也说不太明白(老师没讲,自己也懒得看书,大家不要学我,学好专业基础课很重要!很重要!很重要!重要的话说三遍)

还是网上找的一个解释:(懒得看可以忽略)

符号表在编译程序工作的过程中需要不断收集、记录和使用源程序中一些语法符号的类型和特征等相关信息。这些信息一般以表格形式存储于系统中。如常数表、变量名表、数组名表、过程名表、标号表等等,统称为符号表。对于符号表组织、构造和管理方法的好坏会直接影响编译系统的运行效率。

在编译过程中需要不断汇集和查证出现在源程序中的各种名字的属性和特征等信息编译器使用符号表来记录名字的作用域以及绑定信息编译程序中符号表用来存放语言程序中出现的有关标识符的属性信息,符号表中的信息在编译的不同阶段都用到在语义分析中,符号表所登记的内容将用于语义检查(如检查一个名字的使用和原先的说明是否一致)和产生中间代码在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据。对一个多遍扫描的编译程序,不同遍所用的符号表也往往各有不同。因为每遍所关心的信息各有差异。

下面是一张貌似是pascal语言编译器中的符号表(可以不看,有个大概印象就行)

从编译器角度理解C++中的引用和指针

下面我们简化出一个符号表,专门用来解释变量名和地址之间的关系(重要,必须看)

假设我们定义了一个变量a :

int a = 10;

在编译器的编译的某个阶段(随着编译的进行,符号表是不断变化的)有如下符号表(我自己简化的,实际并不长这个样子

变量名

首地址

类型

空间大小

a

0x3333

int

4字节

10

那么当我们将a++时,编译器会查找符号表,找到变量名为a的条目(符号表本质上就是一个表格,或者说是一个数据库),找到之后,根据a的首地址、类型、值等将a的值变为11

编译器将代码翻译成机器代码后,是没有变量名的,学过汇编的都知道,汇编语言都是直接操作地址的,根本没有变量名。

所以变量名可以理解为编译器符号表的一个索引,我们再做a++运算时,实际上编译器是根据变量名a找到了我们要操作的内存的首地址,然后在根据符号表中记录的属性,对该内存区域进行操作。

所以说变量名可以理解为地址的索引,或者说变量名代表了符号表中的一行。这一行中不进有首地址,还有类型、空间大小、值等。

所以我们要找到变量的地址需要用&(取地址)符号。(当然对于数组是不需要的)

所以我们可以这样说,变量名可以理解为被各种属性修饰的地址(这里的属性指类型、空间大小、值等)。进一步,变量名可以理解为一个受限制的地址(首各种属性的限制

我们知道指针变量中存储的就是符号表中,某一行的首地址字段。然而只有这个首地址,没有那些属性(其他字段的限制),我们能做的事情就会很多:

我们可以人为的给这个首地址分配内存空间(malloc函数)、我们可以人为地给这个地址空间设定访问规则为按double类型访问(malloc时,强制类型转换成double),这也就是说我们可以人为规定首地址的类型和空间大小等属性

这也是指针的强大之处,指针中存的就是首地址,而这个首地址的各种属性都可以由程序员决定。

对吧!

但是通过变量名,我们可以访问到的地址是受限制的,因为在我们写int a= 10的时候,a的地址空间的大小、类型等都是编译器为我们分配和决定的!我们没有权利去做。但是通过声明一个指针,我们就可以自己决定这篇内存的属性!!!!

这也就是指针的强大之处,也是它的可怕之处。

所以一句话总结一下变量名和地址的关系就是:变量名可以理解为一个受各种属性限制的地址(而这些属性,是编译器决定的),指针就是地址,创建一个指针,就是创建一个不受各种属性限制的地址!!

再来说引用,引用就是变量的一个别名字,那我们写,比如int &b = a;这个时候编译器的符号表中就会多一个条目:

变量名

首地址

类型

空间大小

b

0x3333

int

4字节

10

发现没有,除了变量名不一样,其他的都一样!!!所以a和b就是一个东西

那么可以说,引用和指针的区别,就是变量名和指针的区别,进一步简单理解为变量名和首地址的区别!!!!

是我自己的一些想法,有些知识可能存在不准确和错误。。。尽请谅解。。。。

相关文章