Un calificador de tipo es una analogía con los constructores en la programación orientada a objetos .
A partir de 2014 [actualizar]y C11 , hay cuatro calificadores de tipo en C estándar: const
( C89 ), volatile
( C89 ), restrict
( C99 ) y _Atomic
( C11 ); este último tiene un nombre privado para evitar conflictos con los nombres definidos por el usuario. [1] Los dos primeros, const
y volatile
, también están presentes en C++ y son los únicos calificadores de tipo en C++. Por lo tanto, en C++, el término " tipo calificado por cv " (para const y volátil ) se usa a menudo para "tipo calificado", mientras que los términos " tipo calificado por c " y " tipo calificado por v " se usan cuando solo uno de los calificadores es relevante.
De estos, const
es por lejos el más conocido y el más utilizado, ya que aparece en las bibliotecas estándar de C y C++ y se encuentra en cualquier uso significativo de estos lenguajes, que deben satisfacer la corrección constante . Los otros calificadores se utilizan para la programación de bajo nivel y, aunque se usan ampliamente allí, rara vez los utilizan los programadores típicos. Sin embargo, durante un tiempo volatile
algunos programadores de C++ lo usaron para la sincronización durante el subprocesamiento, aunque esto se desaconsejó y ahora está roto en la mayoría de los compiladores.
En D, los constructores de tipo son const
, immutable
, shared
, y inout
. immutable
es una variante más fuerte de const
, que indica datos que nunca pueden cambiar su valor, mientras que const
indica datos que no se pueden cambiar a través de esta referencia: es una vista constante de datos posiblemente mutables. shared
se utiliza para datos compartidos en subprocesos múltiples (como volatile
se usó brevemente para en C++). inout
es un comodín utilizado para permitir que las funciones que no modifican datos (y, por lo tanto, solo se ocupan del tipo no calificado de los datos) devuelvan el mismo tipo calificado que la entrada. const
y immutable
también se pueden utilizar como especificadores de clase de almacenamiento.
En C y C++, un tipo se proporciona en una declaración de función o variable mediante uno o más especificadores de tipo y, opcionalmente, calificadores de tipo. Por ejemplo, una variable entera se puede declarar como:
entero x ;
donde int
es el especificador de tipo. Una variable entera sin signo se puede declarar como:
entero sin signo x ;
donde tanto unsigned
y como int
son especificadores de tipo. Una variable entera constante sin signo se puede declarar como:
constante int sin signo x ;
donde const
es un calificador de tipo, cuyo tipo calificado x
es const unsigned int
y el tipo no calificado es unsigned int
.
Las declaraciones de variables tienen además un especificador de clase de almacenamiento opcional . En realidad, se trata de un tema aparte, distinto del tipo, aunque tambiénconst
se considera que la declaración de una variable tiene implicaciones para la clase de almacenamiento, es decir, que se puede almacenar en una memoria de solo lectura.
El otro calificador en C y C++, volatile
, indica que un objeto puede ser modificado por algo externo al programa en cualquier momento y, por lo tanto, debe volver a leerse desde la memoria cada vez que se accede a él.
El calificador se encuentra con mayor frecuencia en código que manipula hardware directamente (como en sistemas integrados y controladores de dispositivos ) y en aplicaciones multiproceso (aunque a menudo se usa incorrectamente en ese contexto; consulte los enlaces externos en variable volátil ). Se puede usar exactamente de la misma manera que const
en las declaraciones de variables, punteros, referencias y funciones miembro y, de hecho, volatile
a veces se usa para implementar una estrategia de diseño por contrato similar que Andrei Alexandrescu llama volatile
-corrección, [2] aunque esto es mucho menos común que const
-corrección. El volatile
calificador también se puede eliminar con const_cast
, y se puede combinar con el const
calificador como en este ejemplo:
// Establezca una referencia a un registro de hardware de solo lectura que esté asignado en una ubicación de memoria codificada. const volátil int & hardwareRegister = * reinterpret_cast < int *> ( 0x8000 ); int currentValue = hardwareRegister ; // Leer la ubicación de la memoria int newValue = hardwareRegister ; // Leerlo nuevamente hardwareRegister = 5 ; // Error, no se puede escribir en una ubicación constante
Como hardwareRegister
es volatile
, no hay garantía de que contenga el mismo valor en dos lecturas sucesivas, aunque el programador no pueda modificarlo. La semántica aquí indica que el valor del registro es de solo lectura, pero no necesariamente inmutable.
La noción de un calificador de tipo fue introducida, junto con el ejemplo de readonly
(más tarde renombrado const
) por Bjarne Stroustrup en un Memorando Técnico interno de Bell Labs de 1981, [3] e implementada en C con Clases , el predecesor de C++ . [4] En cuanto a la motivación, Stroustrup escribe: [4]
const
fue adoptado en C como parte de la estandarización, y aparece en C89 (y versiones posteriores) junto con otro calificador de tipo, volatile
, que fue inventado por el comité de estándares ANSI C (X3J11). [5] volatile
apareció en 1985; [6] y un uso temprano fue en la compilación del núcleo UNIX para MIPS , para permitir la compilación optimizada al evitar que se apliquen optimizaciones habituales a variables volátiles. [7] Un calificador adicional, noalias
, fue sugerido en la reunión de diciembre de 1987 del comité X3J11, pero fue rechazado; su objetivo finalmente se cumplió con el restrict
calificador en C99. La motivación para noalias
era complementaria a volatile
, es decir, que indicaba que incluso se podían realizar optimizaciones normalmente inseguras. Ritchie no apoyaba mucho los calificadores de tipo, argumentando que no "tenían su peso", pero en última instancia no defendió su eliminación del estándar; [8] sin embargo, se opuso noalias
, y se eliminó del borrador.
Java no tiene calificadores de tipo, y se omite llamativamente const
: una propuesta de 1999 para agregarlo fue rechazada, en particular porque agregarlo después del hecho y luego cambiar la biblioteca estándar para usarlo de manera consistente habría roto la compatibilidad. [9] Sin embargo, Java inicialmente dejó abierta la posibilidad de implementar const
, notable en que const
es una palabra reservada , aunque en realidad no se usa como palabra clave . En cambio, Java tiene la palabra clave orientada a objetos final
, que se usa para calificar atributos (y, por lo tanto, también para variables locales) como constantes, pero no para calificar tipos.
Otros lenguajes adoptan un enfoque diferente, considerando la constancia como una propiedad de un identificador (o de un enlace de nombre ), no de un tipo. Por lo tanto, dichos lenguajes tienen identificadores constantes (que corresponden a "variables" que no varían) con una única asignación, pero no tienen una noción de corrección constante: dado que la constancia no es parte del tipo, no hay posibilidad de que haya un desajuste de tipos. Algunos ejemplos incluyen Ada 83 con objetos constantes y una constant
palabra clave, [10] [a] y Java con la final
palabra clave.