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

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

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

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

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

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

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

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

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

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

假设我们定义了一个变量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就是一个东西

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

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

从编译器角度理解C++中的引用和指针的更多相关文章

  1. IL角度理解C#中字段,属性与方法的区别

    IL角度理解C#中字段,属性与方法的区别 1.字段,属性与方法的区别 字段的本质是变量,直接在类或者结构体中声明.类或者结构体中会有实例字段,静态字段等(静态字段可实现内存共享功能,比如数学上的pi就 ...

  2. 多态原理探究-从C++编译器角度理解多态的实现原理

    理论知识: 当类中声明虚函数时,编译器会在类中生成一个虚函数表. 虚函数表是一个存储类成员函数指针的数据结构. 虚函数表是由编译器自动生成与维护的. virtual成员函数会被编译器放入虚函数表中. ...

  3. c++中的引用与指针的区别

    http://blog.csdn.net/lyd_253261362/article/details/4323691 c++中的引用与指针的区别 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存 ...

  4. 理解Java中的引用传递和值传递

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习 ...

  5. (转载)理解Java中的引用传递和值传递

      关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天 ...

  6. [ZZ]C++中,引用和指针的区别

    (1) 引用总是指向一个对象,没有所谓的 null reference .所有当有可能指向一个对象也由可能不指向对象则必须使用 指针. 由于C++ 要求 reference 总是指向一个对象所以 re ...

  7. 【C++】C++中的引用与指针

    想必大家对C++中的指针都有所了解,但是什么是引用呢?C++11标准引入了“引用”的新功能. 引用 引用(reference):给对象起了另外一个名字,引用类型引用(refers to)另外一种类型, ...

  8. C中有关引用和指针的异同

    参考于https://blog.csdn.net/wtzdedaima/article/details/78377201 C语言也学了蛮久的,其实一直都没有用到过或者碰到过引用的例子.前端时间再全面复 ...

  9. 使用java实现单链表----(java中的引用就是指针)

    //一直以为java中没有指针,其实java的引用就是指针,只不过堆栈中的引用储存了在堆中的地址,可以看做java中的指针.public class sibgleLink<E> { // ...

随机推荐

  1. jQuery Ajax 实例 全解析(转)

    1. load( url, [data], [callback] ) :载入远程 HTML 文件代码并插入至 DOM 中. url (String) : 请求的HTML页的URL地址. data (M ...

  2. 踩坑实录 使用 cardview 时报错 error: No resource identifier found for attribute 'cardCornerRadius' in package 'com.xxxxx.xxx'

    在项目中引用 cardview 卡片布局,编译时 Android Studio 报出下面图片中红框标记的错误: 出现这种情况的原因在于没有导入 cardview 卡片布局相应的依赖包,因此我们需要在 ...

  3. [原]node.js使用感想

    最近尝试了使用node.js,但因为不是太深入(小项目,还没做完),所以不能谈心得谈经验,就来谈谈使用感想. node.js和以往的cgi接口的服务器+cgi程序(如apache+phpmod)中的单 ...

  4. POPTEST老李谈钩子

    poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...

  5. 老李推荐:第8章5节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-运行测试脚本

    老李推荐:第8章5节<MonkeyRunner源码剖析>MonkeyRunner启动运行过程-运行测试脚本   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化 ...

  6. 老李推荐: 第8章4节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动AndroidDebugBridge 4

    这一部分的代码逻辑关系是这样的: 344行: 一个外部循环每次从上次保存下来的设备列表获得一个设备Device实例 350行: 再在一个内部循环从最新的设备列表中获得一个设备Device实例 353行 ...

  7. 老李分享:《Linux Shell脚本攻略》 要点(二)

    老李分享:<Linux Shell脚本攻略> 要点(二)   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课 ...

  8. Uva 11609 Teams (组合数学)

    题意:有n个人,选不少于一个人参加比赛,其中一人当队长,有多少种选择方案. 思路:我们首先C(n,1)选出一人当队长,然后剩下的 n-1 人组合的总数为2^(n-1),这里用快速幂解决 代码: #in ...

  9. 看Lucene源码必须知道的基本概念

    终于有时间总结点Lucene,虽然是大周末的,已经感觉是对自己的奖励,毕竟只是喜欢,现在的工作中用不到的.自己看源码比较快,看英文原著的技术书也很快.都和语言有很大关系.虽然咱的技术不敢说是部门第一的 ...

  10. JDBC基础学习(四)—数据库事务

    一.事务基本认识 1.事务的概述      为了保证数据库中数据的一致性,数据的操作应当是离散的成组的逻辑单元.当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应当全部视 ...