"registrar" palabra clave en C?


¿Qué hace la palabra clave register en el lenguaje C? He leído que se utiliza para optimizar, pero no está claramente definido en ningún estándar. ¿Sigue siendo relevante y, si es así, cuándo lo usaría?

Author: Sathish, 2009-02-23

17 answers

Es una sugerencia para el compilador de que la variable será muy utilizada y que usted recomienda que se mantenga en un registro de procesador si es posible.

La mayoría de los compiladores modernos hacen eso automáticamente, y son mejores en elegirlos que nosotros los humanos.

 307
Author: Brian Knoblauch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-22 03:19:09

Me sorprende que nadie haya mencionado que no se puede tomar una dirección de variable de registro, incluso si el compilador decide mantener la variable en la memoria en lugar de en el registro.

Así que usando register no se gana nada (de todos modos el compilador decidirá por sí mismo dónde poner la variable) y se pierde el operador & - no hay razón para usarlo.

 61
Author: qrdl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-25 16:51:43

Le dice al compilador que intente usar un registro de CPU, en lugar de RAM, para almacenar la variable. Los registros están en la CPU y el acceso es mucho más rápido que la RAM. Pero es solo una sugerencia para el compilador, y puede que no siga adelante.

 33
Author: Andrew Barnett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-23 16:14:15

Sé que esta pregunta es sobre C, pero la misma pregunta para C++ se cerró como un duplicado exacto de esta pregunta. Por lo tanto, esta respuesta puede no aplicarse a C.


El último borrador del estándar C++11, N3485 , dice esto en 7.1.1 / 3:

Un especificador register es una pista para la implementación de que la variable así declarada será muy utilizada. [nota: La sugerencia puede ser ignorada y en la mayoría de las implementaciones será ignorada si la dirección de la se toma variable. Este uso está en desuso ... -nota final ]

En C++ (pero no en C), el estándar no indica que no se puede tomar la dirección de una variable declarada register; sin embargo, debido a que una variable almacenada en un registro de CPU a lo largo de su vida no tiene una ubicación de memoria asociada con ella, intentar tomar su dirección no sería válido, y el compilador ignorará la palabra clave register para permitir tomar la dirección.

 18
Author: bwDraco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-29 21:45:55

No ha sido relevante durante al menos 15 años, ya que los optimizadores toman mejores decisiones sobre esto que usted. Incluso cuando era relevante, tenía mucho más sentido en una arquitectura de CPU con muchos registros, como SPARC o M68000 que en Intel con su escasez de registros, la mayoría de los cuales están reservados por el compilador para sus propios fines.

 17
Author: Paul Tomblin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-23 16:20:27

En realidad, register le dice al compilador que la variable no se alias con cualquier otra cosa en el programa (ni siquiera char).

Eso puede ser explotado por los compiladores modernos en una variedad de situaciones, y puede ayudar al compilador bastante en código complejo - en código simple los compiladores pueden resolver esto por su cuenta.

De lo contrario, no sirve para ningún propósito y no se utiliza para la asignación de registros. No suele incurrir en degradación de rendimiento para especificarlo, siempre y cuando su el compilador es lo suficientemente moderno.

 12
Author: Rupert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-17 00:36:12

He leído que se utiliza para optimizar, pero no está claramente definido en ningún estándar.

De hecho, está claramente definido por el estándar C. Citando el N1570 draft sección 6.7.1 párrafo 6 (otras versiones tienen la misma redacción):

Una declaración de un identificador para un objeto con clase de almacenamiento especificador register sugiere que el acceso al objeto sea lo más rápido posible posible. La medida en que tales las sugerencias son efectivas es implementación-definida.

El operador unario & no puede aplicarse a un objeto definido con register, y register no puede utilizarse en una declaración externa.

Hay algunas otras reglas (bastante oscuras) que son específicas para register objetos calificados:

  • Definir un objeto array con register tiene un comportamiento indefinido.
    Corrección: Es legal definir un objeto array con register, pero no se puede hacer cualquier cosa útil con tal objeto (indexar en una matriz requiere tomar la dirección de su elemento inicial).
  • El especificador _Alignas (nuevo en C11) no se puede aplicar a tal objeto.
  • Si el nombre del parámetro pasado a la macro va_start está calificado register, el comportamiento es indefinido.

Puede haber algunos más; descargue un borrador del estándar y busque "registrarse" si está interesado.

Como su nombre indica, el original significado de register era requerir que un objeto se almacenara en un registro de CPU. Pero con las mejoras en la optimización de compiladores, esto se ha vuelto menos útil. Las versiones modernas del estándar C no se refieren a registros de CPU, porque ya no (necesitan) asumir que existe tal cosa (hay arquitecturas que no usan registros). La sabiduría común es que aplicar register a una declaración de objeto es más probable que empeore el código generado, porque interfiere con el propio compilador asignación de registros. Todavía puede haber algunos casos en los que es útil (por ejemplo, si realmente sabe con qué frecuencia se accederá a una variable, y su conocimiento es mejor de lo que un compilador de optimización moderno puede averiguar).

El principal efecto tangible de register es que evita cualquier intento de tomar la dirección de un objeto. Esto no es particularmente útil como una sugerencia de optimización, ya que se puede aplicar solo a variables locales, y un compilador de optimización puede ver por sí mismo que la dirección del objeto no está tomada.

 11
Author: Keith Thompson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-20 15:39:58

Storytime!

C, como lenguaje, es una abstracción de un ordenador. Te permite hacer cosas, en términos de lo que hace una computadora, que es manipular la memoria, hacer matemáticas, imprimir cosas, etc.

Pero C es solo una abstracción. Y en última instancia, lo que está extrayendo de es el lenguaje ensamblador. Assembly es el lenguaje que lee una CPU, y si lo usas, haces cosas en términos de la CPU. ¿Qué hace una CPU? Básicamente, lee de memoria, hace matemáticas y escribe en memoria. La CPU no solo hace matemáticas con los números en la memoria. Primero, tienes que mover un número de memoria a memoria dentro de la CPU llamado register. Una vez que haya terminado de hacer lo que tenga que hacer con este número, puede moverlo de nuevo a la memoria normal del sistema. ¿Por qué usar la memoria del sistema? El número de registros es limitado. Solo obtienes alrededor de un centenar de bytes en los procesadores modernos, y los procesadores populares más antiguos eran aún más fantásticamente limitados (El 6502 tenía 3 registros de 8 bits para su uso gratuito). Por lo tanto, su operación matemática promedio se ve como:

load first number from memory
load second number from memory
add the two
store answer into memory

Mucho de eso es... no matemáticas. Esas operaciones de carga y almacenamiento pueden tardar hasta la mitad de su tiempo de procesamiento. C, siendo una abstracción de computadoras, liberó al programador de la preocupación de usar y hacer malabares con los registros, y dado que el número y el tipo varían entre computadoras, C coloca la responsabilidad de la asignación de registros únicamente en el compilador. Con una excepción.

Cuando declaras una variable register, le estás diciendo al compilador " Yo, I tener la intención de que esta variable se utilice mucho y / o sea de corta duración. Si fuera tú, trataría de guardarlo en un registro."Cuando el estándar C dice que los compiladores no tienen que hacer nada, es porque el estándar C no sabe para qué computadora está compilando, y podría ser como el 6502 anterior, donde los 3 registros son necesarios solo para operar, y no hay registro de repuesto para mantener su número. Sin embargo, cuando dice que no puede tomar la dirección, es porque los registros no tienen dirección. Son las manos del procesador. Dado que el compilador no tiene que darle una dirección, y ya que no puede tener una dirección en absoluto, varias optimizaciones están ahora abiertas para el compilador. Podría, por ejemplo, mantener el número en un registro siempre. No tiene que preocuparse por dónde está almacenado en la memoria de la computadora (más allá de la necesidad de recuperarlo de nuevo). Incluso podría hacer un juego de palabras en otra variable, darle a otro procesador, darle una ubicación cambiante, etc.

Tl; dr: Efímero variables que hacen muchas matemáticas. No declare demasiados a la vez.

 6
Author: Orion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-09 05:35:21

Estás jugando con el sofisticado algoritmo de coloreado de gráficos del compilador. Esto se utiliza para la asignación de registros. Bueno, mayormente. Actúa como una pista para el compilador that eso es cierto. Pero no ignorado en su totalidad ya que no se le permite tomar la dirección de una variable de registro (recuerde que el compilador, ahora en su misericordia, tratará de actuar de manera diferente). Lo que en cierto modo te está diciendo que no lo uses.

La palabra clave fue usada mucho, mucho tiempo atrás. Cuando había tan pocos registros que podría contarlos todos usando su dedo índice.

Pero, como he dicho, obsoleto no significa que no pueda usarlo.

 4
Author: dirkgently,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-23 16:21:30

Solo una pequeña demostración (sin ningún propósito del mundo real) para la comparación: al eliminar las palabras clave register antes de cada variable, este fragmento de código tarda 3.41 segundos en mi i7 (GCC), con register el mismo código se completa en 0.7 segundos.

#include <stdio.h>

int main(int argc, char** argv) {

     register int numIterations = 20000;    

     register int i=0;
     unsigned long val=0;

    for (i; i<numIterations+1; i++)
    {
        register int j=0;
        for (j;j<i;j++) 
        {
            val=j+i;
        }
    }
    printf("%d", val);
    return 0;
}
 4
Author: Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-29 06:52:40

Register notificaría al compilador que el codificador creía que esta variable sería escrita/leída lo suficiente como para justificar su almacenamiento en uno de los pocos registros disponibles para el uso de variables. La lectura / escritura de registros suele ser más rápida y puede requerir un conjunto de código operativo más pequeño.

Hoy en día, esto no es muy útil, ya que la mayoría de los optimizadores de compiladores son mejores que usted a la hora de determinar si un registro debe usarse para esa variable, y por cuánto tiempo.

 2
Author: billjamesdev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-23 16:16:31

En compiladores de C soportados intenta optimizar el código para que el valor de la variable se mantenga en un registro de procesador real.

 2
Author: Dana Holt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-23 16:17:12

Durante los años setenta, al principio del lenguaje C, se ha introducido la palabra clave register para permitir al programador dar pistas al compilador, diciéndole que la variable se usaría muy a menudo, y que debería ser prudente mantener su valor en uno de los registros internos del procesador.

Hoy en día, los optimizadores son mucho más eficientes que los programadores para determinar las variables que tienen más probabilidades de mantenerse en registros, y el optimizador no siempre tenga en cuenta la sugerencia del programador.

Muchas personas recomiendan equivocadamente no usar la palabra clave register.

¡Veamos por qué!

La palabra clave register tiene un efecto secundario asociado: no se puede hacer referencia (obtener la dirección de) una variable de tipo de registro.

Las personas que aconsejan a otros no usar registros toman erróneamente esto como un argumento adicional.

Sin embargo, el simple hecho de saber que no se puede tomar la dirección de una variable de registro, permite el compilador (y su optimizador) para saber que el valor de esta variable no se puede modificar indirectamente a través de un puntero.

Cuando en un cierto punto del flujo de instrucciones, una variable de registro tiene su valor asignado en el registro de un procesador, y el registro no se ha utilizado desde entonces para obtener el valor de otra variable, el compilador sabe que no necesita volver a cargar el valor de la variable en ese registro. Esto permite evitar el costoso acceso inútil a la memoria.

Do sus propias pruebas y obtendrá mejoras de rendimiento significativas en sus bucles más internos.

C_register_side_effect_performance_boost

 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-08 13:55:29

El compilador Visual C++ de Microsoft ignora la palabra clave register cuando la optimización global de asignación de registros (la bandera del compilador /Oe) está habilitada.

Ver registrar Palabra clave en MSDN.

 1
Author: M. Dudley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-25 16:49:19

La palabra clave Register le dice al compilador que almacene la variable en particular en los registros de la CPU para que pueda ser accesible rápidamente. Desde el punto de vista de un programador, la palabra clave register se usa para las variables que se usan mucho en un programa, para que el compilador pueda acelerar el código. Aunque depende del compilador si mantener la variable en los registros de la CPU o en la memoria principal.

 1
Author: Sanjeev Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-14 11:08:17

He probado la palabra clave register bajo QNX 6.5.0 usando el siguiente código:

#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>

int main(int argc, char *argv[]) {
    uint64_t cps, cycle1, cycle2, ncycles;
    double sec;
    register int a=0, b = 1, c = 3, i;

    cycle1 = ClockCycles();

    for(i = 0; i < 100000000; i++)
        a = ((a + b + c) * c) / 2;

    cycle2 = ClockCycles();
    ncycles = cycle2 - cycle1;
    printf("%lld cycles elapsed\n", ncycles);

    cps = SYSPAGE_ENTRY(qtime) -> cycles_per_sec;
    printf("This system has %lld cycles per second\n", cps);
    sec = (double)ncycles/cps;
    printf("The cycles in seconds is %f\n", sec);

    return EXIT_SUCCESS;
}

Obtuve los siguientes resultados:

- > 807679611 ciclos transcurridos

- > Este sistema tiene 3300830000 ciclos por segundo

- > Los ciclos en segundos es ~0.244600

Y ahora sin registro int:

int a=0, b = 1, c = 3, i;

Tengo:

- > 1421694077 ciclos transcurridos

- > Este sistema tiene 3300830000 ciclos por segundo

- > Los ciclos en segundos es ~0.430700

 1
Author: Daniel B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-30 10:15:44

Register indica al compilador que optimice este código almacenando esa variable en particular en registros y luego en memoria. es una petición al compilador, el compilador puede o no considerar esta petición. Puede utilizar esta función en caso de que se acceda a algunas de sus variables con mucha frecuencia. Por ejemplo: Un bucle.

Una cosa más es que si declara una variable como registro, entonces no puede obtener su dirección, ya que no está almacenada en la memoria. obtiene su asignación en el registro de CPU.

 0
Author: flying-high,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-14 11:30:46