4.1.8b register
§1 Sinopsis
La palabra clave register es un especificador de tipo de
almacenamiento ("storage class specifier"); se utiliza para indicar al compilador que ciertas variables (normalmente del tipo int y
char) deben ser almacenadas en los registros del procesador en lugar de la pila
( 1.3.2). Son las denominadas
variables de registro. La razón de este "capricho" hay que buscarla en la velocidad. Ocurre que los registros,
aunque de poca capacidad y en número limitado, corresponden a zonas de almacenamiento de los
procesadores cuyo acceso es excepcionalmente rápido [1].
Nota: recordemos que los especificadores de almacenamiento permitidos en C++ son: auto; register; static; extern y mutable.
§2 Este especificador de almacenamiento solo puede aplicarse a
variables automáticas y a parámetros de funciones (por consiguiente no pueden ser globales o estáticas). De hecho, cuando el
especificador register se aplica a la declaración de variables (por ejemplo, int, char, float),
también implica duración automática (
4.1.5).
Ejemplo:
register int i; //
Error!
register char c; // Error!
func( register int p1, register long l2) { // Ok.
register int x; // Ok.
}
Otro ejemplo: ( 9.1).
Ténga en cuenta que no es posible obtener la dirección
de una variable de registro. Es decir, no se puede aplicar a una de estas variables el operador de referencia
(
4.9.11b).
§3 El tipo y número de variables de registro que pueden usarse es dependiente de la implementación. Normalmente
se utiliza para aumentar la velocidad de ejecución en determinadas zonas de código (en controles de bucle por ejemplo). El
compilador puede ignorarlas completamente o ignorar las que sobrepasen el máximo permitido.
Nota: el programador C++ puede "solicitar" que una variable local entera o un puntero sean situados en un registro si hay alguno disponible; caso de no haber ninguno, la variable es tratada simplemente como un objeto automático sin que exista ninguna advertencia de error. En realidad, C++ puede ignorar completamente la petición de colocación en registros, ya que esta se basa en un análisis heurístico del compilador sobre el modo de ser utilizada la variable. El Estándar C++ advierte que la mayoría de las implementaciones ingnorarán la solicitud de register para una variable si en algún punto del código se obtiene su dirección.
§4 Como hemos visto, los modernos compiladores actúan con bastante libertad a la hora de realizar determinadas
optimizaciones, como puede ser la colocación automática de ciertas variables en registros, pero en ocasiones conviene que el
compilador no haga tal cosa por su cuenta. Esto puede conseguirse con el modificador
volatile ( 4.1.9)
§5 Opciones de compilación
Dependiendo de determinadas opciones en el comando de compilación
( 1.4.3), el compilador C++Builder puede
adoptar tres posturas respecto a la forma de utilizar los registros del procesador para almacenar variables:
-r Utilizar variables de registro cuando se estime pertinente. Este es el valor por defecto.
-r- Deshabilitar totalmente el uso de variables de registro.
-rd Utilizar variables de registro solamente cuando se solicite explícitamente con la palabra clave register.
Teniendo en cuenta que los modernos compiladores C++ son
bastante "inteligentes" en este sentido, la mejor opción es adoptar el valor por defecto y dejar que sea el
propio compilador el que decida que variables son idóneas para ser declaradas "de registro".
Tema
relacionado
Paso de argumentos de funciones a registros en BC++ (
4.4.6bW1).
[1] Los microprocesadores de arquitectura Intel® disponen
como mínimo, de 8 registros de propósito general. Precisamente la
capacidad en bits de cada uno de los registros es lo que caracteriza al
procesador; los hay de 8, 16, 32, 64 etc. bits. Normalmente
su acceso solo es posible mediante el lenguaje ensamblador. En los lenguajes de mayor, nivel su manejo es asumido de modo automático
por el compilador. Sin embargo, recordar que C++ permite la inserción directa de sentencias ensamblador en su código fuente
( 4.10). En este
sentido puede decirse que es un lenguaje que permite un control de muy bajo nivel sobre el procesador.