Pregunta

En C, no podemos usar y para averiguar la dirección de una variable de registro pero en C ++ podemos hacer lo mismo. ¿Por qué es legal en C ++, pero no en C? Por favor alguien puede explicar este concepto en profundidad.

¿Fue útil?

Solución

He aquí un extracto de la Sección 6.7.1 (nota 101) de la estándar C99 (pdf) :

  

La aplicación puede tratar cualquier declaración register simplemente como una declaración auto. Sin embargo, si o no el almacenamiento direccionable se utiliza realmente, la dirección de cualquier parte de un objeto declarado con registro especificador de clase de almacenamiento no se puede calcular , ya sea explícitamente (mediante el uso del operador & unario como se discute en 6.5.3.2) o implícita (mediante la conversión de un nombre de matriz a un puntero como se discute en 6.3.2.1). Por lo tanto, el único operador que puede ser aplicado a una matriz declara con register especificador de clase de almacenamiento es sizeof.

Y a partir de la Sección 7.1.1, párrafo 3 de la C ++ estándar (pdf) :

  

Un especificador register tiene la misma semántica que un especificador auto junto con un toque a la aplicación que se va a utilizar el objeto de modo declarado. [Nota: la indirecta puede ser ignorado y en la mayoría de las implementaciones que se tendrá en cuenta si se toma la dirección del objeto. nota -fin]

cositas curiosos sobre register

El C ++ grupo (WG21) quiere despreciar register :

  

La palabra clave register sirve muy pequeña función, que no ofrece más que un indicio de que una nota que dice es normalmente ignorada. Cabe desaprobado en esta versión de la norma, liberando el nombre reservado para su uso en un futuro estándar, al igual que auto ha sido re-utilizado en esta ocasión por ser similarmente inútil.

     

Notas de la de marzo de 2009 reunión:

     

El consenso del GTC estaba a favor de desaprobación register.

Mira lo que el grupo C99 dijo (WG14) sobre register (pdf) en una reunión:

  

acuerdo general para despreciar la palabra clave “auto”. Hay que pedirle WG21 volver a   el uso anterior de “register” (sin dirección)? No, esto no va a volar con WG21.

Otros consejos

La palabra clave de registro es sólo un indicio y se puede ignorar. La mayoría de los compiladores de C ++ lo ignoran todo el tiempo, pero cualquier compilador de C ++ lo ignorarán si se toma la dirección de la variable, o crear una referencia a él.

Por otro lado, un compilador de C ++ no Tienes para ignorar "registrar" sólo porque se toma la dirección de la variable. En teoría, el compilador podría almacenar en un registro y le dará un valor de puntero magia que de alguna manera está asignada al registro detrás de las escenas, pero que sería mucho trabajo para muy poca ganancia, por lo que no compilador (que yo sepa) hace nada por el estilo.

Desde registro es ignorable en C, así, sospecho que la prohibición explícita en contra de tomar las direcciones de las variables de registro fue simplemente para aliviar los compiladores de C de la carga de la comprobación de esto.

La parte relevante de la norma C ++ es 7.1.1.3:

  

Un especificador de registro tiene la misma semántica que un especificador de automóviles junto con un toque a la aplicación que el objeto declarado así se va a utilizar. [Nota: la indirecta puede ser ignorado y en la mayoría de las implementaciones que se tendrá en cuenta si se toma la dirección del objeto. nota -fin]

Lo sentimos acerca de la super tarde respuesta.

El problema es que, en C, register originalmente significaba almacenar valores en un registro que es por qué sólo int y char se pueden utilizar para ello. Pero con el tiempo y, especialmente, C ++ estándar, se amplió a "acceso rápido" en lugar de "en el registro de la CPU". Así que en C ++, una matriz tal vez un tipo register pero sabemos que no es posible almacenar matrices en un registro de la CPU. Por lo tanto, es lógicamente aceptable para hacer frente a un registro C ++ (en el sentido anterior), pero aún no tienen sentido si los valores son en realidad en un registro de la CPU.

Asumo que la palabra clave no habría incluso hizo que en el idioma si no fuera por la compatibilidad C. Aunque no puedo hablar con cualquier autoridad, si esto es así, me parece que hay una razón práctica para que sea legal más allá de simplemente un estándar reforzado "el compilador es más inteligente que tú" cláusula: C ++ lleva direcciones de las cosas sin el permiso C más fácilmente que lo hace. Específicamente: funciones miembro, y referencias.

Debido a que las funciones miembro requieren un parámetro this implícita, sería imposible llamarlos desde un objeto declarado register. En C, no hay nada que prohíba de decir register struct X x;, por lo que este tipo de lenguaje tendría que estar permitido en C ++ [ya que C-compatibilidad es la única razón, incluso existe la palabra clave]. Pero si prohíbe llamar a funciones miembro, así como tomar las direcciones, que también cubre la llamada al constructor inicial. En esencia, que no funcionaría en los tipos no-POD. Así que terminan con un especificador de clase de almacenamiento que sólo es válida para un pequeño subconjunto de los tipos legales, cuando todo el resto se puede utilizar para cualquier cosa.

También no puede crear referencias a esos objetos, a pesar de que, técnicamente, el compilador no tiene que tratar como referencias punteros. register int i; int& x; no está obligado a tener espacio para dos variables, pero si más tarde lo hace &x se termina con un puntero a i. Por lo que la construcción inicial tiene que pasarán a ser ilegal. Aunque esto parece no sea un problema, ya que las referencias no existen en C todos modos, volviendo a nuestro punto anterior, los tipos de POD declaradas con el especificador register ya no se pueden copiar. El constructor de copia compilador-proporcionado es de la forma X::X(const X&) o X::X(X&) según sea apropiado.

Por lo tanto, con el fin de mantener la compatibilidad C, que tienen que hacer register única como un especificador de clase de almacenamiento en el que no se aplica a todos los tipos, y modificar al menos dos partes diferentes de la norma en otros lugares [especificar que pueda no crear una referencia a una variable declarada con el especificador register, y trabajar de alguna manera alrededor de las referencias para copiar POD]. O, podrían decir "está bien para tomar la dirección" y dejar que los compiladores de decidir si es o no cumplir las peticiones. Algo que estaban planeando en hacer de todos modos.

Una variable de registro no tiene una dirección, se llevó a cabo (al menos se supone que tendrá lugar) en un registro de la CPU. Puesto que el modificador de registro no es más que un indicio, si se fuerza el compilador para generar código para extraer su dirección, el modificador va a ser ignorado y que va a terminar con una variable ordinaria celebrada en la memoria.

Para responder a su pregunta directamente, cualquiera que le permite tomar la dirección de una variable de registro (su puesto original se contradice en sí ..) le permite ignorar su propia pista y debe por lo menos una advertencia. OMI la aplicación correcta sería la de no permitir tomar la dirección de una variable de registro.

Lo importante es recordar que "registrar" es sólo una sugerencia para el compilador (un ser inútil en ese, nunca he visto ninguna mejora en la velocidad, y la mayoría de los compiladores, probablemente, simplemente lo ignoran). C y C ++ son a la vez les permite hacer caso omiso de sus "consejos" y mantener la variable en la memoria. Por supuesto, si se toma la dirección de la variable, que obligará a asignar un lugar en la memoria.

C y C ++ sólo tienen diferentes reglas sobre lo que puede hacer, ya que son diferentes idiomas. El diseñadores C ++ decidieron permitirá obtener la dirección de una variable de registro, ya que no duele nada; C no permite que lo haga, ya que obligaría a la memoria.

Pensando en ello más, la restricción de C es, probablemente, por la misma razón que las variables tienen que ser declarado al comienzo del bloque el compilador puede Esquema de la memoria para las variables, ya que se encuentra con ellas, sin tener en cuenta cómo se utiliza más adelante en la función.

Esto sólo es una conjetura, pero dudo que pueda tomar la dirección de un registro en C ++ debido a un pensar tal, simplemente no existe. C ++, probablemente no utiliza un registro en su caso particular. Observe que el register calificador clase de almacenamiento es sólo un indicio de que el compilador (y la mayoría si no todos los compiladores modernos felizmente lo ignoran por completo).

C y C ++ son dos idiomas diferentes, con un gran subconjunto común. Es por eso que algunas cosas son diferentes entre ellos.

Si bien no entiendo su pregunta, register es (al menos en C ++) un indicio de que una variable se pueda acceder con mayor frecuencia, y nada más. En C, significa que no puede tomar la dirección con el operador unario &, lo que hizo que una cierta cantidad de sentido en ese momento. En los primeros días de C, se esperaba que el compilador podría no molesta la asignación de memoria para la variable, y por lo que no sería necesariamente una dirección a tomar.

(Informática normalmente tienen registros, que son partes de acceso rápido de la CPU, y por lo tanto el almacenamiento más rápida de acceso. Una variable podría vivir en un registro, en lugar de en la memoria, en caso de que causó un mejor rendimiento.)

Hoy en día, casi todos los compiladores son lo suficientemente sofisticados para hacer su propia asignación mejor que el programador puede, por lo que usar register es casi siempre inútil.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top