变量和指针有什么区别?


10

Whist阅读了一篇概述OO和函数式编程差异的文章我遇到了函数指针。自从我完成计算机科学学位(2003年)以来已经有一段时间了,所以我查找了一些指针来刷新自己的记忆。

指针是包含对内存地址的引用的变量。如果存在,则可以认为它们指向该内存地址中包含的数据。或者,如本文中的情况一样,它们可能指示代码段的入口点,并可用于调用该代码。

为什么这不同于变量?变量是内存地址的符号名称,编译器会将名称替换为实际地址。这意味着变量包含对内存位置的引用,如果存在这样的数据,则可以认为变量指向该地址处的数据。

如果行为不同(也许不能在运行时重新分配指针,或者只能分配符号变量名称,不能分配其他任何值),这是否意味着它只是特定类型的变量,即指针类型?以相同的方式,声明为整数类型的变量在其用途上受到编译的限制。

我在这里想念什么?


4
指针实际上不是一种类型,其语义解释是变量的内容是地址。当然要注意,有两个地址,即指针的地址(即变量存储的位置)和指针引用的地址(变量地址处的实际数据)。指针是引用的一种
卢克·马西森

Answers:


8

您的问题在几个方面都很有趣,因为它需要对几个问题进行仔细区分。但是在我看来,您的愿景基本上是正确的。为了避免使我的答案有偏见,在撰写大部分答案之前,我没有阅读您的参考文献。

首先,您的陈述Variables are symbolic names for memory addresses几乎是正确的,但是却使概念及其通常的实现感到困惑。变量实际上只是一个容器,可以包含可以更改的值。通常,此容器在计算机上以内存空间的形式实现,其特点是地址和大小,因为变量可能包含需要用或多或少的信息表示的对象。

但是我将主要考虑语言语义的更抽象的观点,而与实现技术无关。

因此,从抽象的角度来看,变量只是容器。这样的容器不需要名称。但是,语言通常具有通过将标识符与标识符相关联来命名的变量,因此可以通过标识符来表达对变量的使用。变量实际上可以通过各种别名机制具有多个标识符。变量也可以是较大变量的子部分:例如,数组变量的单元格可以通过指定数组变量和单元格的索引来命名,但也可以通过别名与标识符关联。

我故意使用有点中性的单词容器,以避免调用其他可能在语义上加载的单词。实际上,它与wilipedia中描述引用概念非常接近,后者经常与内存地址混淆。指针一词本身通常被理解为一个内存地址,但是在考虑大多数高级语言时,我认为这没有意义,并且在您所指的讨论文件中可能不合适(尽管可以使用地址),因为它不合适。指的是特定的实现。但是,它适合于C之类的语言,该语言应该更接近于实现概念和机器体系结构。

实际上,如果您在实现级别查看变量或值,则可能存在多个间接的系统,即“机器级别的指针”,但是对于用户而言(并且应该是)不可见的,因此抽象的观点我开发可以是有效的。对于大多数编程语言,用户不必担心,甚至不必了解实现,因为对于给定的语言,实现可能有很大不同。对于某些有意接近机器体系结构的语言(例如C),它是汇编语言的高级替代品,而汇编语言几乎与显式二进制编码有直接关系,但对于大多数应用程序来说,它们的使用水平太低,这可能并非如此。情况。

语言的用户应该知道的是,值和相关的操作是什么,可以在何处包含它们,如何将它们与名称相关联,命名系统如何工作,如何使用新的语言,有时甚至应该少得多。定义各种值,等等。

612

不变值与标识符的关联通常称为常数。从这个意义上说,文学是常数。

“值容器”也可以视为值,并且它们与标识符的关联在您一直在使用的“天真”意义上是变量。因此,您可能会说变量是“容器常数”。

现在您可能想知道将标识符与值(常量声明)相关联或将值分配给变量(即,将值存储在定义为容器常量的容器中)之间的区别是什么?本质上,声明可以看作是定义符号的操作,该符号将作为语法实体的标识符与作为语义实体的某个值相关联。赋值是一种纯粹的语义操作,它修改状态,即修改容器的值。从某种意义上说,声明是一个无语义影响的元概念,除了为语义实体提供命名(即句法)机制外。

实际上,赋值是在程序执行时动态发生的语义操作,而声明具有更多的句法性质,通常独立于执行而在程序的文本中进行解释。这就是为什么静态作用域(即文本作用域)通常是理解标识符含义的自然方法。

毕竟,我可以说指针值只是容器的另一个名称,而指针变量是容器变量,即可以包含另一个容器的容器(常量)(某些人可能会对包含游戏施加限制)类型系统)。

关于代码,您声明 [pointers] might indicate the entry point to a section of code and can be used to call that code。其实这不是真的。从高层次或实现的角度来看,一段代码通常是没有意义的。从高级的角度来看,代码通常包含标识符,并且您必须在声明它们的静态上下文中解释这些标识符。但是实际上,由于递归是动态(运行时)现象,因此实际上可能存在相同静态上下文的重复,并且代码只能在静态上下文的适当动态实例中执行。这有点复杂,但是其结果是,正确的概念是闭包的概念,即将一段代码与要解释标识符的环境相关联。闭包是适当的语义概念,即是适当定义的语义值。然后,您可以拥有闭合常量,闭合变量,

函数是一个闭包,通常带有一些参数来定义或初始化其某些实体(常量和变量)。

我跳过了关于这些机制使用的许多变化。

闭包可用于以命令性或功能性语言定义OO结构。实际上,以这种方式完成了有关OO风格的早期工作(可能在名称之前)。

我快速浏览的您参考的论文似乎是由有能力的人撰写的有趣文章,但如果您对多种语言及其底层计算模型没有丰富的经验,则可能不容易阅读。

但是请记住:情人眼中有很多事情,只要他保持一致的看法即可。观点可能会有所不同。

这回答了你的问题了吗?

PS:这是一个很长的答案。如果您认为其中的某些部分不够充分,请明确指出它是什么。谢谢。


我不得不仔细阅读了几次,但我认为它确实回答了我的问题,是的。虽然我的定义过于实现为中心的想法,一个指针变量的特定类型似乎是准确的,即“指针值是容器的另一个名称而已,和指针变量是一个容器变量” 在这里我就不得到的区别是:包含代码块地址的指针与包含容器的容器(包含闭包)之间。静态上下文和执行中的程序之间的区别吗?
NectarSoft 2014年

1
@NectarSoft区别仅在代码块和闭包之间。我的意思是,就其本身而言,与任何上下文隔离,代码块通常没有任何意义。如果我告诉您“ 如果莫米河口大于波罗戈维斯,那么toves就会胜过 ”,该句子没有任何意义,因为您错过了定义所有这些概念的上下文。该静态上下文通常是包含代码片段的文本。问题在于此静态上下文本身可以具有多个运行时实例,并且代码片段必须仅引用其中一个。
babou 2014年

1
@NectarSoft(续)因此,闭包值是代码片段与为该片段赋予含义的静态上下文动态实例的关联。相同代码片段与相同静态上下文的不同动态实例的关联提供了不同的闭包。通常,您的代码可以使用属于上下文的变量,但是对于上下文的每个动态实例,它都是不同的变量,尽管其名称(静态定义)保持不变。这是否可以解决问题,还是应该在答案中建立示例(注释格式受限制)?
babou 2014年

谢谢,它确实阐明了这个问题,同时提出了其他问题,我将花一些时间来思考。例如,如果每个闭包都需要一个不同的指针,则该指针似乎成为动态上下文的一部分,因此属于闭包内!我也想知道闭包的边界和闭包的层次结构,因为与静态代码块关联并由指针引用的这些上下文中的每一个在其自身的闭包中必然是变量。但是所有这些都不是话题,所以当我再次被卡住时,我会做一些阅读,或者提出另一个问题
NectarSoft 2014年

@NectarSoft实际上。在构建闭包时,您尝试将与代码关联的上下文限制为对代码赋予适当含义所必需的内容(最多避免一些实际的约束,以避免对信息进行微观管理)。这可以静态确定。
babou 2015年

2

区别在于定义和应用,指针是一个专用变量,用于保存另一个变量的内存地址;用面向对象的术语,可能会认为指针是从称为变量的通用类继承其行为的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.