En programación informática , una variable es una ubicación de almacenamiento abstracta emparejada con un nombre simbólico asociado , que contiene una cantidad conocida o desconocida de datos u objeto denominado valor ; o en términos más simples, una variable es un contenedor nombrado para un conjunto particular de bits o tipo de datos (como entero , flotante , cadena , etc.). [1] Una variable puede eventualmente asociarse con o identificarse por una dirección de memoria . El nombre de la variable es la forma habitual de hacer referencia al valor almacenado, además de hacer referencia a la variable misma, dependiendo del contexto. Esta separación de nombre y contenido permite que el nombre se use independientemente de la información exacta que representa. El identificador en el código fuente de la computadora puede vincularse a un valor durante el tiempo de ejecución , y el valor de la variable puede cambiar durante el curso de la ejecución del programa . [2] [3] [4] [5]
Las variables en programación pueden no corresponderse directamente con el concepto de variables en matemáticas . Este último es abstracto y no tiene referencia a un objeto físico como la ubicación de almacenamiento. El valor de una variable informática no es necesariamente parte de una ecuación o fórmula como en matemáticas. A las variables en programación informática se les dan con frecuencia nombres largos para que sean relativamente descriptivos de su uso, mientras que las variables en matemáticas suelen tener nombres concisos, de uno o dos caracteres, para abreviar en la transcripción y manipulación.
La ubicación de almacenamiento de una variable puede estar referenciada por varios identificadores diferentes, una situación conocida como alias . Asignar un valor a la variable mediante uno de los identificadores cambiará el valor al que se puede acceder mediante los otros identificadores.
Los compiladores deben reemplazar los nombres simbólicos de las variables por las ubicaciones reales de los datos. Si bien el nombre, el tipo y la ubicación de una variable suelen permanecer fijos, los datos almacenados en la ubicación pueden cambiar durante la ejecución del programa.
En los lenguajes de programación imperativos , los valores pueden ser accedidos o modificados en cualquier momento. En los lenguajes puramente funcionales y lógicos , las variables están ligadas a expresiones y mantienen un único valor durante toda su vida útil debido a los requisitos de transparencia referencial . En los lenguajes imperativos, el mismo comportamiento lo exhiben las constantes (con nombre) (constantes simbólicas), que normalmente se contrastan con las variables (normales).
Según el sistema de tipos de un lenguaje de programación, las variables pueden almacenar únicamente un tipo de datos específico (por ejemplo, entero o cadena ). Alternativamente, un tipo de datos puede estar asociado únicamente con el valor actual, lo que permite que una única variable almacene cualquier cosa compatible con el lenguaje de programación. Las variables son los contenedores para almacenar los valores.
Variables y alcance:
Se puede utilizar un identificador que hace referencia a una variable para acceder a la variable con el fin de leer el valor, alterar el valor o editar otros atributos de la variable, como permisos de acceso, bloqueos , semáforos , etc.
Por ejemplo, una variable puede ser referenciada por el identificador " total_count
" y la variable puede contener el número 1956. Si la misma variable r
también es referenciada por el identificador " " y se usa este identificador " r
", el valor de la variable se modifica a 2009, entonces leer el valor usando el identificador " total_count
" arrojará un resultado de 2009 y no 1956.
Si una variable solo se referencia mediante un único identificador, dicho identificador puede llamarse simplemente el nombre de la variable ; de lo contrario, podemos hablar de él como uno de los nombres de la variable . Por ejemplo, en el ejemplo anterior, el identificador " total_count
" es el nombre de la variable en cuestión y " r
" es otro nombre de la misma variable.
El alcance de una variable describe en qué parte del texto de un programa se puede utilizar la variable, mientras que la extensión (también llamada duración ) de una variable describe en qué momento de la ejecución de un programa la variable tiene un valor (significativo). El alcance de una variable afecta a su extensión. El alcance de una variable es en realidad una propiedad del nombre de la variable, y la extensión es una propiedad de la ubicación de almacenamiento de la variable. Estas no deben confundirse con el contexto (también llamado entorno ), que es una propiedad del programa y varía según el punto del texto o la ejecución del programa (consulte alcance: una descripción general) . Además, la duración del objeto puede coincidir con la duración de la variable, pero en muchos casos no está vinculada a ella.
El alcance es una parte importante de la resolución de nombres de una variable. La mayoría de los lenguajes definen un alcance específico para cada variable (así como para cualquier otra entidad nombrada), que puede diferir dentro de un programa determinado. El alcance de una variable es la porción del texto del programa para la cual el nombre de la variable tiene significado y para la cual se dice que la variable es "visible". La entrada en ese alcance generalmente comienza la vida útil de una variable (cuando entra en contexto) y la salida de ese alcance generalmente termina su vida útil (cuando sale de contexto). Por ejemplo, una variable con " alcance léxico " es significativa solo dentro de una cierta función/ subrutina , o más precisamente dentro de un bloque de expresiones/declaraciones (según el alcance de la función o el alcance del bloque ); esta es una resolución estática, que se puede realizar en tiempo de análisis o en tiempo de compilación. Alternativamente, una variable con alcance dinámico se resuelve en tiempo de ejecución, en función de una pila de enlaces global que depende del flujo de control específico . Las variables a las que solo se puede acceder dentro de ciertas funciones se denominan " variables locales ". Una " variable global ", o una con alcance indefinido, puede ser referenciada en cualquier parte del programa.
Por otro lado, la extensión es un aspecto de tiempo de ejecución ( dinámico ) de una variable. Cada enlace de una variable a un valor puede tener su propia extensión en tiempo de ejecución. La extensión del enlace es la parte del tiempo de ejecución del programa durante la cual la variable continúa haciendo referencia al mismo valor o ubicación de memoria. Un programa en ejecución puede entrar y salir de una extensión dada muchas veces, como en el caso de un cierre .
A menos que el lenguaje de programación cuente con recolección de basura , una variable cuya extensión sobreviva permanentemente a su alcance puede resultar en una fuga de memoria , por lo que la memoria asignada para la variable nunca puede liberarse ya que la variable que se usaría para referenciarla para fines de desasignación ya no es accesible. Sin embargo, puede ser permisible que una vinculación de variable se extienda más allá de su alcance, como ocurre en los cierres de Lisp y las variables locales estáticas de C ; cuando la ejecución pasa nuevamente al alcance de la variable, la variable puede volver a usarse. Una variable cuyo alcance comienza antes que su extensión se dice que no está inicializada y, a menudo, tiene un valor arbitrario indefinido si se accede a ella (ver puntero salvaje ), ya que aún no se le ha dado explícitamente un valor particular. Una variable cuya extensión termina antes de su alcance puede convertirse en un puntero colgante y considerarse no inicializada una vez más ya que su valor ha sido destruido. Las variables descritas por los dos casos anteriores pueden decirse que están fuera de la extensión o no vinculadas . En muchos lenguajes, es un error intentar usar el valor de una variable cuando está fuera de la extensión. En otros lenguajes, esto puede dar lugar a resultados impredecibles . Sin embargo, a esa variable se le puede asignar un nuevo valor, lo que le otorga una nueva extensión.
Para ahorrar espacio, el espacio de memoria necesario para una variable se puede asignar solo cuando la variable se utiliza por primera vez y se puede liberar cuando ya no se necesita. Una variable solo es necesaria cuando está dentro del ámbito, por lo que comenzar el ciclo de vida de cada variable cuando entra en el ámbito puede dar lugar a variables no utilizadas. Para evitar desperdiciar dicho espacio, los compiladores a menudo advierten a los programadores si una variable se declara pero no se utiliza.
Se considera una buena práctica de programación hacer que el alcance de las variables sea lo más estrecho posible para que las diferentes partes de un programa no interactúen accidentalmente entre sí modificando las variables de las demás. Hacerlo también evita la acción a distancia . Las técnicas comunes para hacerlo son hacer que las diferentes secciones de un programa utilicen diferentes espacios de nombres o hacer que las variables individuales sean "privadas" a través del alcance de variable dinámico o el alcance de variable léxico .
Muchos lenguajes de programación emplean un valor reservado (a menudo llamado null o nil ) para indicar una variable no válida o no inicializada.
En lenguajes de tipado estático como C , C++ , Java o C# , una variable también tiene un tipo , lo que significa que solo se pueden almacenar en ella determinados tipos de valores. Por ejemplo, una variable de tipo " entero " no puede almacenar valores de texto. [6]
En lenguajes de tipado dinámico como Python , el tipo de una variable se infiere por su valor y puede cambiar de acuerdo con este. En Common Lisp , ambas situaciones existen simultáneamente: a una variable se le asigna un tipo (si no se declara, se asume que es , el supertipoT
universal ) que existe en tiempo de compilación. Los valores también tienen tipos, que se pueden comprobar y consultar en tiempo de ejecución.
La tipificación de variables también permite resolver polimorfismos en tiempo de compilación. Sin embargo, esto es diferente del polimorfismo utilizado en llamadas a funciones orientadas a objetos (conocidas como funciones virtuales en C++ ), que resuelve la llamada en función del tipo de valor en lugar de los supertipos que se le permite tener a la variable.
Las variables suelen almacenar datos simples, como números enteros y cadenas literales, pero algunos lenguajes de programación permiten que una variable también almacene valores de otros tipos de datos . Dichos lenguajes también pueden permitir que las funciones sean polimórficas paramétricas . Estas funciones operan como variables para representar datos de múltiples tipos. Por ejemplo, una función nombrada length
puede determinar la longitud de una lista. Dicha length
función puede ser polimórfica paramétrica al incluir una variable de tipo en su firma de tipo , ya que la cantidad de elementos en la lista es independiente de los tipos de los elementos.
Los parámetros formales (o argumentos formales ) de las funciones también se denominan variables. Por ejemplo, en este segmento de código de Python ,
>>> def addtwo ( x ): ... devuelve x + 2 ... >>> addtwo ( 5 ) 7
La variable nombrada x
es un parámetro porque se le asigna un valor cuando se llama a la función. El entero 5 es el argumento que le otorga x
su valor. En la mayoría de los lenguajes, los parámetros de función tienen alcance local. Esta variable específica nombrada x
solo puede ser referenciada dentro de la addtwo
función (aunque, por supuesto, otras funciones también pueden tener variables llamadas x
).
Los detalles de la asignación de variables y la representación de sus valores varían ampliamente, tanto entre lenguajes de programación como entre implementaciones de un lenguaje determinado. Muchas implementaciones de lenguajes asignan espacio para variables locales , cuya extensión dura una única llamada de función en la pila de llamadas , y cuya memoria se recupera automáticamente cuando la función regresa. De manera más general, en la vinculación de nombres , el nombre de una variable se vincula a la dirección de algún bloque particular (secuencia contigua) de bytes en la memoria, y las operaciones en la variable manipulan ese bloque. La referencia es más común para variables cuyos valores tienen tamaños grandes o desconocidos cuando se compila el código. Tales variables hacen referencia a la ubicación del valor en lugar de almacenar el valor en sí, que se asigna desde un grupo de memoria llamado montón .
Las variables enlazadas tienen valores. Sin embargo, un valor es una abstracción, una idea; en la implementación, un valor se representa mediante algún objeto de datos , que se almacena en algún lugar de la memoria de la computadora. El programa, o el entorno de ejecución , debe reservar memoria para cada objeto de datos y, dado que la memoria es finita, garantizar que esta memoria se libere para su reutilización cuando el objeto ya no sea necesario para representar el valor de alguna variable.
Los objetos asignados desde el montón deben ser recuperados, especialmente cuando los objetos ya no son necesarios. En un lenguaje de recolección de basura (como C# , Java , Python, Golang y Lisp ), el entorno de ejecución recupera automáticamente los objetos cuando las variables existentes ya no pueden hacer referencia a ellos. En lenguajes que no son de recolección de basura, como C , el programa (y el programador) deben asignar memoria explícitamente y luego liberarla para recuperar su memoria. Si no lo hace, se producen fugas de memoria , en las que el montón se agota mientras se ejecuta el programa, lo que supone el riesgo de una falla eventual por agotar la memoria disponible.
Cuando una variable hace referencia a una estructura de datos creada dinámicamente, es posible que algunos de sus componentes solo sean accesibles indirectamente a través de la variable. En tales circunstancias, los recolectores de basura (o funciones de programa análogas en lenguajes que carecen de recolectores de basura) deben lidiar con un caso en el que solo se necesita recuperar una parte de la memoria accesible desde la variable.
A diferencia de sus contrapartes matemáticas, las variables y constantes de programación suelen tener nombres de varios caracteres, por ejemplo, COST
o total
. Los nombres de un solo carácter se utilizan con mayor frecuencia solo para variables auxiliares; por ejemplo, i
, j
, k
para variables de índice de matriz .
Algunas convenciones de nombres se aplican a nivel de lenguaje como parte de la sintaxis del lenguaje, que incluye el formato de los identificadores válidos. En casi todos los lenguajes, los nombres de las variables no pueden comenzar con un dígito (0-9) y no pueden contener caracteres de espacio en blanco. El hecho de que se permitan o no los signos de puntuación en los nombres de las variables varía de un lenguaje a otro; muchos lenguajes solo permiten el guión bajo ("_") en los nombres de las variables y prohíben todos los demás signos de puntuación. En algunos lenguajes de programación, se añaden sigilos (símbolos o signos de puntuación) a los identificadores de las variables para indicar el tipo de datos o el alcance de la variable.
La distinción entre mayúsculas y minúsculas en los nombres de las variables también varía entre los distintos idiomas y algunos requieren el uso de una determinada distinción entre mayúsculas y minúsculas al nombrar ciertas entidades; [nota 1] La mayoría de los idiomas modernos distinguen entre mayúsculas y minúsculas, mientras que algunos idiomas más antiguos no lo hacen. Algunos idiomas reservan ciertas formas de nombres de variables para su propio uso interno; en muchos idiomas, los nombres que comienzan con dos guiones bajos ("__") a menudo entran en esta categoría.
Sin embargo, más allá de las restricciones básicas impuestas por un lenguaje, la denominación de las variables es en gran medida una cuestión de estilo. A nivel de código de máquina , no se utilizan nombres de variables, por lo que los nombres exactos elegidos no importan a la computadora. Por lo tanto, los nombres de las variables las identifican, por lo demás son solo una herramienta para que los programadores hagan que los programas sean más fáciles de escribir y comprender. El uso de nombres de variables mal elegidos puede hacer que el código sea más difícil de revisar que los nombres no descriptivos, por lo que a menudo se recomiendan nombres claros. [7] [8]
Los programadores suelen crear y respetar pautas de estilo de código que ofrecen orientación sobre cómo nombrar las variables o imponen un esquema de nombres preciso. Los nombres más cortos se escriben más rápido, pero son menos descriptivos; los nombres más largos suelen hacer que los programas sean más fáciles de leer y que el propósito de las variables sea más fácil de entender. Sin embargo, la verbosidad extrema en los nombres de las variables también puede dar lugar a un código menos comprensible.
Podemos clasificar las variables en función de su duración. Los diferentes tipos de variables son estáticas, dinámicas de pila, dinámicas de montón explícitas y dinámicas de montón implícitas. Una variable estática también se conoce como variable global, está vinculada a una celda de memoria antes de que comience la ejecución y permanece en la misma celda de memoria hasta la terminación. Un ejemplo típico son las variables estáticas en C y C++. Una variable dinámica de pila se conoce como variable local, que se vincula cuando se ejecuta la declaración y se desasigna cuando el procedimiento regresa. Los principales ejemplos son las variables locales en los subprogramas de C y los métodos de Java. Las variables dinámicas de montón explícitas son celdas de memoria sin nombre (abstractas) que se asignan y desasignan mediante instrucciones explícitas de tiempo de ejecución especificadas por el programador. Los principales ejemplos son los objetos dinámicos en C++ (a través de new y delete) y todos los objetos en Java. Las variables dinámicas de montón implícitas están vinculadas al almacenamiento de montón solo cuando se les asignan valores. La asignación y liberación ocurren cuando se reasignan valores a las variables. Como resultado, las variables dinámicas de montón implícitas tienen el mayor grado de flexibilidad. Los ejemplos principales son algunas variables en JavaScript, PHP y todas las variables en APL.