stringtranslate.com

Constante (programación informática)

En programación informática , una constante es un valor que el programa no modifica durante su ejecución normal . Cuando se asocia a un identificador , se dice que una constante tiene "nombre", aunque los términos "constante" y "constante con nombre" suelen usarse indistintamente. Esto contrasta con una variable , que es un identificador con un valor que puede modificarse durante la ejecución normal. Para simplificar, los valores de las constantes permanecen, mientras que los valores de las variables varían, de ahí sus nombres.

Las constantes son útiles tanto para los programadores como para los compiladores : para los programadores, son una forma de código autodocumentado y permiten razonar sobre la corrección , mientras que para los compiladores, permiten verificaciones en tiempo de compilación y de ejecución que verifican que no se violen los supuestos de constancia, [a] y permiten o simplifican algunas optimizaciones del compilador .

Existen varias realizaciones específicas de la noción general de constante, con distinciones sutiles que a menudo se pasan por alto. Las más significativas son: constantes de tiempo de compilación (valoradas estáticamente), constantes de tiempo de ejecución (valoradas dinámicamente), objetos inmutables y tipos de constantes ( const).

Algunos ejemplos típicos de constantes de tiempo de compilación incluyen constantes matemáticas, valores de estándares (aquí unidad máxima de transmisión ) o valores de configuración interna (aquí caracteres por línea ), como estos ejemplos de C :

const float PI = 3.1415927 ; // precisión máxima de punto flotante simple const unsigned int MTU = 1500 ; // Ethernet v2, RFC 894 const unsigned int COLUMNS = 80 ;                

Ejemplos típicos de constantes de tiempo de ejecución son valores calculados en función de las entradas a una función, como este ejemplo de C++ :

void f ( std :: string s ) { const tamaño_t l = s . length (); // ... }         

Usar

Algunos lenguajes de programación hacen una distinción sintáctica explícita entre símbolos constantes y variables, por ejemplo, considerando la asignación a una constante como un error de sintaxis, mientras que en otros lenguajes se consideran sintácticamente iguales (ambos simplemente un identificador), y la diferencia en el tratamiento es semántica (la asignación a un identificador es sintácticamente válida, pero si el identificador es una constante es semánticamente inválido).

Un valor constante se define una sola vez y se puede hacer referencia a él muchas veces a lo largo de un programa. El uso de una constante en lugar de especificar el mismo valor varias veces puede simplificar el mantenimiento del código (como en el caso de no repetirse ) y puede ser autodocumental al proporcionar un nombre significativo para un valor, por ejemplo, PIen lugar de 3.1415926.

Comparación con literales y macros

Existen varias formas principales de expresar un valor de datos que no cambia durante la ejecución del programa y que son consistentes en una amplia variedad de lenguajes de programación. Una forma muy básica es simplemente escribir un número, carácter o cadena literal en el código del programa, lo cual es sencillo en C, C++ y lenguajes similares.

En lenguaje ensamblador, los números y caracteres literales se procesan mediante las instrucciones de "modo inmediato" disponibles en la mayoría de los microprocesadores. El nombre "inmediato" proviene de que los valores están disponibles inmediatamente desde el flujo de instrucciones , en lugar de cargarse indirectamente mediante la búsqueda de una dirección de memoria. [1] Por otro lado, los valores más largos que la longitud de palabra del microprocesador, como cadenas y matrices, se manejan indirectamente y los ensambladores generalmente proporcionan una pseudooperación "data" para incrustar dichas tablas de datos en un programa.

Otra forma es definiendo una macro simbólica . Muchos lenguajes de programación de alto nivel y muchos ensambladores ofrecen una función de macro donde el programador puede definir, generalmente al comienzo de un archivo fuente o en un archivo de definición separado, nombres para diferentes valores. Luego, un preprocesador reemplaza estos nombres con los valores apropiados antes de compilar, lo que da como resultado algo funcionalmente idéntico al uso de literales, con las ventajas de velocidad del modo inmediato. Debido a que puede ser difícil mantener un código donde todos los valores se escriben literalmente, si un valor se usa de manera repetitiva o no obvia, a menudo se le asigna un nombre mediante una macro.

Una tercera forma es declarar y definir una variable como "constante". Una variable global o estática se puede declarar (o un símbolo se puede definir en el ensamblador) con un calificador de palabra clave como const, constant, o final, lo que significa que su valor se establecerá en tiempo de compilación y no se debe poder cambiar en tiempo de ejecución. Los compiladores generalmente colocan constantes estáticas en la sección de texto de un archivo de objeto junto con el código en sí, a diferencia de la sección de datos donde se guardan los datos inicializados no constantes. Algunos compiladores pueden producir una sección específicamente dedicada a las constantes. Se puede aplicar protección de memoria a esta área para evitar que punteros erróneos sobrescriban dichas constantes.

Estas constantes difieren de los literales en varios aspectos. Los compiladores generalmente colocan una constante en una única ubicación de memoria identificada por un símbolo, en lugar de distribuirla por todo el ejecutable como sucede con una macro. Si bien esto excluye las ventajas de velocidad del modo inmediato, existen ventajas en la eficiencia de la memoria y los depuradores pueden trabajar con estas constantes en tiempo de ejecución. Además, si bien las macros pueden redefinirse accidentalmente por archivos de encabezado conflictivos en C y C++, las constantes conflictivas se detectan en tiempo de compilación.

Según el lenguaje, las constantes pueden ser sin tipo o con tipo. En C y C++, las macros proporcionan lo primero, mientras que constproporcionan lo segundo:

#define PI 3.1415926535constante flotante pi2 = 3.1415926535 ;    

Mientras que en Ada, existen tipos numéricos universales que se pueden utilizar, si se desea:

pi  :  constante  : =  3,1415926535 ;pi2  :  constante  flotante  :=  3.1415926535 ;

con la variante sin tipo convirtiéndose implícitamente al tipo apropiado en cada uso. [2]

Constantes con valores dinámicos

Además de las constantes estáticas descritas anteriormente, muchos lenguajes procedimentales como Ada y C++ extienden el concepto de constante hacia variables globales que se crean en el momento de la inicialización, variables locales que se crean automáticamente en el momento de la ejecución en la pila o en los registros, hacia la memoria asignada dinámicamente a la que se accede mediante un puntero y hacia las listas de parámetros en los encabezados de funciones.

Las constantes con valores dinámicos no designan una variable como residente en una región específica de la memoria, ni los valores se establecen en tiempo de compilación. En código C++ como

float func ( const float CUALQUIER COSA ) { const float XYZ = algunaVariableGlobal * algunaOtraFunción ( CUALQUIER COSA ); ... }          

Las expresiones con las que se inicializa la constante no son constantes en sí mismas. El uso de la constante no es necesario aquí para la legalidad del programa o la corrección semántica, pero tiene tres ventajas:

  1. Es claro para el lector que el objeto no se modificará más una vez configurado.
  2. Los intentos de cambiar el valor del objeto (por parte de programadores posteriores que no comprenden completamente la lógica del programa) serán rechazados por el compilador.
  3. El compilador puede realizar optimizaciones de código sabiendo que el valor del objeto no cambiará una vez creado. [3]

Las constantes con valores dinámicos se originaron como una característica del lenguaje con ALGOL 68. [ 3] Los estudios de código Ada y C++ han demostrado que las constantes con valores dinámicos se usan con poca frecuencia, típicamente para el 1% o menos de los objetos, cuando podrían usarse mucho más, ya que alrededor del 40-50% de los objetos locales que no son de clase son realmente invariantes una vez creados. [3] [4] Por otro lado, estas "variables inmutables" tienden a ser predeterminadas en los lenguajes funcionales, ya que favorecen los estilos de programación sin efectos secundarios (por ejemplo, la recursión) o hacen que la mayoría de las declaraciones sean inmutables por defecto, como ML . Los lenguajes puramente funcionales incluso prohíben los efectos secundarios por completo.

La constante se utiliza a menudo en las declaraciones de funciones, como una promesa de que cuando se pasa un objeto por referencia, la función llamada no lo cambiará. Según la sintaxis, tanto un puntero como el objeto al que se apunta pueden ser constantes, aunque normalmente se prefiere esto último. Especialmente en C++ y C, la disciplina de garantizar que las estructuras de datos adecuadas sean constantes en todo el programa se denomina corrección constante .

Parámetros de función constante

En C/C++, es posible declarar el parámetro de una función o método como constante. Esto es una garantía de que este parámetro no pueda ser modificado inadvertidamente después de su inicialización por el invocador. Si el parámetro es un tipo predefinido (integrado), se invoca por valor y no puede modificarse. Si es un tipo definido por el usuario, la variable es la dirección del puntero, que tampoco puede modificarse. Sin embargo, el contenido del objeto puede modificarse sin límites. Declarar parámetros como constantes puede ser una forma de señalar que este valor no debe modificarse, pero el programador debe tener en cuenta que las comprobaciones sobre la modificación de un objeto no pueden ser realizadas por el compilador.

Además de esta característica, en C++ también es posible declarar una función o un método como const. Esto evita que dichas funciones o métodos modifiquen cualquier cosa que no sean variables locales.

En C#, la palabra clave constexiste, pero no tiene el mismo efecto para los parámetros de función, como ocurre en C/C++. Sin embargo, hay una forma de "estimular" al compilador para que realice la comprobación, aunque es un poco complicada. [5]

Constantes orientadas a objetos

En el lenguaje orientado a objetos , una estructura de datos o un objeto constante se denomina " inmutable ". El hecho de que un objeto sea inmutable confiere algunas ventajas en el diseño de programas. Por ejemplo, se lo puede "copiar" simplemente copiando su puntero o referencia, lo que evita una operación de copia que consume mucho tiempo y conserva la memoria.

Los lenguajes orientados a objetos como C++ extienden la constancia aún más. Los miembros individuales de una estructura o clase pueden hacerse constantes incluso si la clase no lo es. Por el contrario, la mutablepalabra clave permite cambiar un miembro de clase incluso si un objeto se instancia como const.

En C++, incluso las funciones pueden ser constantes. Esto significa que solo se puede llamar a una función constante para un objeto instanciado como constante; una función constante no modifica ningún dato no mutable.

C# tiene tanto un calificador constcomo un readonly; su const es solo para constantes de tiempo de compilación, mientras que readonlyse puede usar en constructores y otras aplicaciones de tiempo de ejecución.

Java

Java tiene un calificador llamado finalque impide cambiar una referencia y garantiza que nunca apunte a un objeto diferente. Esto no impide que se realicen cambios en el objeto al que se hace referencia. El calificador de Java finales básicamente equivalente a un const puntero en C++. No proporciona las otras características de const.

En Java , el calificador finalindica que el miembro de datos o la variable afectada no se puede asignar, como se muestra a continuación:

int final i = 3 ; i = 4 ; // Error! No se puede modificar un objeto "final"       

Debe ser decidible por los compiladores donde finalse inicializa la variable con el marcador y debe realizarse solo una vez, o la clase no se compilará. Las palabras clave finalde Java y C++ consttienen el mismo significado cuando se aplican con variables primitivas.

const int i = 3 ; // Declaración de C++ i = 4 ; // ¡Error!        

En lo que respecta a los punteros, una finalreferencia en Java significa algo similar a constun puntero en C++. En C++, se puede declarar un "tipo de puntero constante".

Foo * const bar = mem_location ; // tipo de puntero constante     

En este caso, bardebe inicializarse en el momento de la declaración y no puede volver a modificarse, pero lo que apunta es modificable, es decir, es válido. Simplemente no puede apuntar a otra ubicación. Las referencias finales en Java funcionan de la misma manera, excepto que pueden declararse sin inicializar.*bar = value

final Foo i ; // una declaración de Java   

Nota: Java no admite punteros. [6] Esto se debe a que los punteros (con restricciones) son la forma predeterminada de acceder a los objetos en Java, y Java no utiliza asteriscos para indicarlos. Por ejemplo, i en el último ejemplo es un puntero y se puede utilizar para acceder a la instancia.

También se puede declarar un puntero a datos de "sólo lectura" en C++.

constante Foo * bar ;  

Aquí barse puede modificar para señalar cualquier cosa, en cualquier momento; sólo que el valor señalado no se puede modificar a través bar del puntero.

En Java no existe un mecanismo equivalente, por lo que tampoco existen constmétodos. En Java no se puede exigir la corrección constante, aunque mediante el uso de interfaces y la definición de una interfaz de solo lectura para la clase y su transmisión, se puede garantizar que los objetos puedan pasarse por el sistema de forma que no puedan modificarse.

El marco de colecciones de Java proporciona una forma de crear un contenedor inmutable de una Collectionvía y métodos similares.Collections.unmodifiableCollection()

Un método en Java puede declararse "final", lo que significa que no puede anularse en subclases.

DO#

En C# , el calificador readonlytiene el mismo efecto sobre los miembros de datos que finalen Java y que consten C++; el modificador consttiene un efecto similar (pero tipificado y con alcance de clase) al de #defineen C++. El otro efecto inhibidor de la herencia de Java finalcuando se aplica a métodos y clases se induce en C# con la ayuda de la palabra clave sealed.

A diferencia de C++, C# no permite que los métodos y parámetros se marquen como const. Sin embargo, también se pueden pasar subclases de solo lectura, y .NET Framework proporciona cierta compatibilidad para convertir colecciones mutables en inmutables que se pueden pasar como contenedores de solo lectura.

Por paradigma

El tratamiento de las constantes varía significativamente según el paradigma de programación . La corrección constante es un problema en lenguajes imperativos como C++ porque, por defecto, las vinculaciones de nombres suelen crear variables , que pueden variar, como sugiere el nombre, y, por lo tanto, si uno desea marcar una vinculación como constante, esto requiere alguna indicación adicional. [b] En otros paradigmas de lenguaje de programación surgen problemas relacionados, y se encuentran algunos análogos a la corrección constante.

En la programación funcional , los datos son típicamente constantes por defecto, en lugar de variables por defecto. En lugar de asignar un valor a una variable (un espacio de almacenamiento con un nombre y un valor potencialmente variable), se crea una vinculación de un nombre a un valor, como por medio de la letconstrucción en muchos dialectos de Lisp . En algunos lenguajes funcionales, particularmente los multiparadigmáticos como Common Lisp , modificar datos es algo común, mientras que en otros se evita o se considera excepcional; este es el caso de Scheme (otro dialecto de Lisp), que utiliza la set!construcción para modificar datos, con el signo de exclamación ! llamando la atención sobre esto. Dichos lenguajes logran los objetivos de corrección constante por defecto, llamando la atención sobre la modificación en lugar de la constancia.

En varios lenguajes orientados a objetos , existe el concepto de objeto inmutable , que se utiliza particularmente para tipos básicos como cadenas; algunos ejemplos notables incluyen Java, JavaScript, Python y C#. Estos lenguajes varían en cuanto a si los tipos definidos por el usuario se pueden marcar como inmutables y pueden permitir que campos particulares (atributos) de un objeto o tipo se marquen como inmutables.

En algunos lenguajes multiparadigma que permiten estilos tanto funcionales como orientados a objetos, ambas características pueden combinarse. Por ejemplo, en OCaml, los campos de objeto son inmutables de forma predeterminada y deben marcarse explícitamente con la palabra clave mutablepara que sean mutables, mientras que en Scala, las vinculaciones son explícitamente inmutables cuando se definen con valpara "valor" y explícitamente mutables cuando se definen con varpara "variable".

Convenciones de nombres

Las convenciones de nombres para las constantes varían. Algunas simplemente las nombran como lo harían con cualquier otra variable. Otras usan mayúsculas y guiones bajos para las constantes de una manera similar a su uso tradicional para macros simbólicas, como SOME_CONSTANT. [7] En la notación húngara , un prefijo "k" significa constantes, así como macros y tipos enumerados .

Una convención obligatoria es que en Ruby , cualquier variable que comience con una letra mayúscula se considera una constante, incluidos los nombres de clase.

Véase también

Notas

  1. ^ En algunos casos esto se puede evitar, por ejemplo, utilizando código automodificable o sobrescribiendo la ubicación de la memoria donde se almacena el valor.
  2. ^ Esto no es universal: en Ada, por ejemplo, los parámetros de entrada y los parámetros de bucle son implícitamente constantes.

Referencias

  1. ^ Ej. Información de sistemas IBM. Conjunto de instrucciones: referencia del lenguaje ensamblador para PowerPC.
  2. ^ Booch, Grady (1983). Ingeniería de software con Ada . Benjamin Cummings . Págs. 116-117. ISBN. 0-8053-0600-5.
  3. ^ abc Schilling, Jonathan L. (abril de 1995). "Constantes con valores dinámicos: una característica del lenguaje poco utilizada". Avisos SIGPLAN . 30 (4): 13–20. doi : 10.1145/202176.202177 . S2CID  17489672.
  4. ^ Perkins, JA Prácticas de programación: análisis de código fuente de Ada desarrollado para la Fuerza Aérea, el Ejército y la Marina . Actas TRI-Ada '89. págs. 342–354. doi :10.1145/74261.74287.
  5. ^ Timwi (9 de septiembre de 2010). "Parámetros de función de solo lectura ("similares a" constantes) de C#". Desbordamiento de pila . Consultado el 6 de mayo de 2012 . [...] Luego, puede declarar métodos cuyo tipo de parámetro "diga" si planea cambiar la variable o no:. [...] Esto imita las comprobaciones en tiempo de compilación similares a la constancia en C++. Como señaló correctamente Eric Lippert, esto no es lo mismo que la inmutabilidad. Pero como programador de C++ creo que lo sabe.
  6. ^ "Oracle Technology Network para desarrolladores de Java | Oracle Technology Network | Oracle". Java.sun.com. 14 de agosto de 2013. Consultado el 18 de agosto de 2013 .
  7. ^ Desarrollador de Microsoft Office XP: nombres de constantes