变量(计算机科学)

计算机编程中,变量是一个抽象的存储位置与关联的符号名称配对,其中包含一些已知或未知数的数据对象,称为;或更简单的术语,变量是特定位或数据类型(例如整数floatString等...)的命名容器。变量最终可以与内存地址相关联或确定。根据上下文,变量名是引用存储值的通常方法。名称和内容的这种分离允许该名称独立于其代表的确切信息。计算机源代码中的标识符可以在运行时间绑定到一个,因此在程序执行过程中,变量的值可能会更改。

编程中的变量可能不直接与数学中变量的概念相对应。后者是抽象的,没有提及物理对象(例如存储位置)。计算变量的值不一定像数学中的方程式公式的一部分。计算机编程中的变量经常给出长名,以使其相对描述其使用,而数学的变量通常具有简短的,一个或两个字符的名称,用于转录和操纵。

变量的存储位置可以用几个不同的标识符引用,这种情况称为混叠。使用一个标识符为变量分配值将更改可以通过其他标识符访问的值。

编译器必须用数据的实际位置替换变量的符号名称。虽然变量的名称,类型和位置通常保持固定,但在程序执行过程中可能会更改存储在位置中的数据。

变量的动作

命令式编程语言中,通常可以随时访问更改值。在纯粹的功能逻辑语言中,由于参考透明度的要求,变量与表达式绑定并在整个生命周期内保持单一值。在命令式语言中,(命名)常数(符号常数)表现出相同的行为,通常与(正常)变量形成鲜明对比。

根据编程语言的类型系统,变量只能存储指定的数据类型(例如整数字符串)。另外,数据类型只能与当前值相关联,从而允许单个变量存储编程语言支持的任何内容。变量是存储值的容器。

变量和范围:

  • 自动变量:仅当调用函数时,函数中的每个局部变量才会存在,并且在退出函数时消失。这样的变量称为自动变量。
  • 外部变量:这些是函数外部的变量,可以通过任何函数访问名称。这些变量永久存在。相反,随着函数的调用和退出,即使使它们返回功能后,它们也会保留其价值。

标识符引用变量

引用变量的标识符可用于访问变量,以读取值,更改值或编辑变量的其他属性,例如访问权限,,锁定,信号量,等等。

例如,标识符“ total_count ”可能引用变量,并且该变量可以包含数字1956。如果标识符“ r ”也引用了相同的变量,并且如果使用此标识符“ r ”,则该变量已更改为2009年,然后使用标识符“ total_count ”读取值,将产生2009年的结果,而不是1956年。

如果仅由单个标识符引用变量,则该标识符可以简单地称为变量的名称;否则,我们可以将其作为变量的名称之一。例如,在上一个示例中,标识符“ total_count ”是所讨论的变量的名称,而“ r ”是同一变量的另一个名称。

范围和程度

变量的范围描述了可以在程序文本中使用变量的位置,而变量的范围(也称为寿命)描述了在程序执行中何时具有(有意义的)值。变量的范围会影响其程度。变量的范围实际上是变量名称的属性,而该范围是变量的存储位置的属性。这些内容不应与上下文(也称为环境)混淆,该属性是程序的属性,并且在程序的文本或执行中随着点而变化 - 请参见范围:概述。此外,对象寿命可能与可变的寿命相吻合,但在许多情况下,对象的寿命与其无关。

范围是变量名称分辨率的重要组成部分。大多数语言都为每个变量(以及任何其他命名实体)定义一个特定范围,这在给定程序中可能有所不同。变量的范围是该变量文本的一部分,该文本的名称具有其含义,并且该变量被称为“可见”。进入该范围的入口通常会开始变量的寿命(因为它进入上下文),并从该范围退出通常会结束其寿命(因为它不在上下文中)。例如,一个具有“词汇范围”的变量仅在某个函数/子例程中有意义,或者在表达式/语句的一个块(相应地使用函数范围块范围)内更细微地细化;这是静态分辨率,可在Parse时间或编译时执行。或者,基于取决于特定控制流的全局绑定堆栈,在运行时解决了具有动态范围的变量。仅在某个功能中可访问的变量被称为“局部变量”。可以将“全局变量”或具有不确定范围的一个变量引用到程序中的任何地方。

另一方面,范围是变量的运行时(动态)方面。变量对一个值的每个绑定都可以在运行时具有自身的范围。绑定的范围是程序执行时间的一部分,在此过程中,变量继续指代相同的值或内存位置。运行程序可以输入并留下给定程度多次,例如关闭

除非编程语言具有垃圾收集,否则该变量的范围永久超过其范围可能会导致内存泄漏,否则将永远无法释放为变量分配的内存,因为将其用于Dealllocation目的引用其引用的变量不再是无障碍。但是,可以使变量结合延伸到其范围之外,就像LISP闭合和C静态局部变量一样。当执行回到变量的范围时,可以再次使用该变量。一个变量在其范围之前开始的范围被认为是非专业化的,并且如果访问(请参阅野生指针),通常具有不确定的任意价值,因为它尚未明确给出特定的值。一个变量在其范围之前结束的变量可能会变成一个悬空的指针,并且由于其价值被破坏,因此再次被认为是不可传剂的。前两种情况描述的变量可以说超出没有结合。在许多语言中,尝试使用变量的值超出程度是错误的。在其他语言中,这样做可能会产生不可预测的结果。但是,这样的变量可能会被分配一个新值,从而使其具有新的范围。

为了达到空间效率,只有在不再需要时首先使用和释放变量时,才能分配变量所需的内存空间。仅当变量处于范围时,才需要一个变量,因此,当每个变量进入范围时,它可以为未使用的变量提供空间。为了避免浪费此类空间,编译器通常会警告程序员,如果声明但未使用变量。

它被认为是良好的编程实践,可以使变量的范围与可行性一样狭窄,以便程序的不同部分不会通过修改彼此的变量来偶然地相互作用。这样做也可以防止距离行动。这样做的常见技术是要使程序的不同部分使用不同的名称空间,或者通过动态变量范围词汇变量范围来使单个变量“私有”。

许多编程语言采用保留值(通常命名为nullnil )来表示无效或非直接变量。

打字

静态键入的语言(例如GOML)中,变量也具有类型,这意味着只能将某些值存储在其中。例如,“整数”类型的变量被禁止存储文本值。

动态键入的语言(例如Python)中,变量的类型是根据其值推断的,并且可以根据其值而变化。在共同的LISP中,这两种情况都同时存在:给出一个变量(如果未申报,假定为T ,是通用超级型),该变量存在于编译时。值还具有类型,可以在运行时检查和查询。

变量的键入还允许在编译时解析多态性。但是,这与面向对象的函数调用中使用的多态性不同( C ++中的虚拟函数),该函数基于值类型而不是允许具有变量的超类型来解决调用。

变量通常存储简单的数据,例如整数和文字字符串,但是某些编程语言也允许变量也可以存储其他数据类型的值。这种语言也可以使功能成为参数多态性。这些功能像变量一样运行以表示多种类型的数据。例如,名为length的函数可以确定列表的长度。由于列表中的元素数量与元素类型无关,因此通过在其类型签名中包含类型变量,可以通过在其类型签名中包含类型变量来成为length多态性。

参数

功能的形式参数(或形式参数)也称为变量。例如,在此Python代码段中,

>>> def addtwo(x):
...     return x + 2
...
>>> addtwo(5)
7

命名x 变量是一个参数,因为在调用函数时给出一个值。整数5是赋予x 价值的参数。在大多数语言中,功能参数具有本地范围。这个名为x 特定变量只能在addtwo函数中引用(尽管当然,其他功能也可以具有称为x 变量)。

内存分配

在编程语言和给定语言的实现之间,可变分配的细节及其值的表示差异很大。许多语言实现分配了本地变量的空间,其范围持续到呼叫堆栈上的单个函数呼叫,并且在函数返回时会自动回收其内存。更一般而言,在名称绑定中,变量的名称与内存中字节的某些特定块(连续序列)的地址结合,并且对变量操纵该块的操作。对于编译代码时值大小或未知大小的变量,引用更为常见。这样的变量引用值的位置,而不是存储值本身,该值是从称为的内存池分配的。

界变量具有值。但是,价值是一种抽象,一个想法。在实现中,值由某些数据对象表示,该数据对象存储在计算机内存中。程序或运行时环境必须为每个数据对象搁置内存,并且由于内存是有限的,因此确保在不再需要对象表示某些变量的值时产生此内存以重复使用。

必须收回从堆分配的对象,尤其是在不再需要对象的情况下。在垃圾收集的语言(例如C#Java ,Python,Golang和Lisp )中,当存在的变量无法再参考时,运行时环境会自动回收对象。在非garbage收集的语言(例如C)中,程序(和程序员)必须明确分配内存,然后随后将其释放,以收回其内存。如果没有这样做,则会导致内存泄漏,其中堆在程序运行时会耗尽,因此可能会因耗尽可用内存而最终失败。

当变量是指动态创建的数据结构时,其某些组件只能通过变量间接访问。在这种情况下,垃圾收集器(或缺乏垃圾收集器的语言中的类似程序功能)必须处理一种只有一部分可从变量到达的内存。

命名约定

与数学对应物不同,编程变量和常数通常为多字符名称,例如COSTtotal 。单字符名称最常仅用于辅助变量;例如, ijk用于数组索引变量。

作为语言语法的一部分,在语言层面上执行了一些命名惯例,该语言涉及有效标识符的格式。在几乎所有语言中,变量名不能以数字(0-9)开头,并且不能包含空格字符。是否允许在可变名称中允许标点符号因语言而异。许多语言仅允许可变名称的下划线(“ _”)并禁止所有其他标点符号。在某些编程语言中,将Sigils (符号或标点符号)固定在变量标识符上,以指示变量的数据类型或范围。

可变名称的案例敏感性在语言和某些语言之间也有所不同,需要在命名某些实体中使用某个情况。大多数现代语言都对大小写;一些较旧的语言不是。某些语言为自己的内部使用保留某些形式的可变名称;在许多语言中,名称以两个强调(“ __”)开头通常属于此类别。

但是,除了一种语言施加的基本限制之外,变量的命名在很大程度上是一种风格问题。在机器代码级别上,不使用变量名称,因此所选的确切名称对计算机无关紧要。因此,变量的名称识别它们,因为其余的只是程序员使程序更易于编写和理解的工具。使用不良的变量名称可以使代码比非描述性名称更难查看,因此通常鼓励清楚的名称。

程序员通常会创建并遵守代码样式指南,这些准则提供了有关命名变量或施加精确命名方案的指南。较短的名称键入更快,但描述性较低。更长的名称通常会使程序易于阅读,并且变量的目的更易于理解。但是,可变名称中的极端详细性也可能导致较低的代码。

变量类型(基于寿命)

我们可以根据其寿命对变量进行分类。不同类型的变量是静态的,堆栈动态的,显式的堆动力和隐式堆动力学。静态变量也称为全局变量,在执行开始之前,它与内存单元绑定,并保留到同一内存单元格直到终止。一个典型的示例是C和C ++中的静态变量。一个堆栈 - 动态变量称为局部变量,在执行声明语句时,该变量被绑定,并且在过程返回时将其划分。主要示例是C子程序和Java方法中的局部变量。显式堆动力变量是无名的(抽象)内存单元,它们通过程序员指定的显式运行时指令分配和处理。主要示例是C ++中的动态对象(通过新和删除)以及Java中的所有对象。隐式堆型变量仅在分配值时才绑定到堆存储。将值重新分配到变量时,分配和释放发生。结果,隐式堆动力变量具有最高的灵活性。主要示例是JavaScript,PHP和APL中所有变量中的一些变量。

也可以看看