Análisis profundo de Const Qualifier en C

8 minutos de lectura

avatar de usuario
Jack

¿Dónde está un const la variable se almacena exactamente y cómo cambia su comportamiento? Di por ejemplo:

const int i=10; // stores where ?  
main()  
{  
   const int j=20; //stores where?   
   return 0;  
}  

Si la respuesta es Segmento de código, ¿cómo funciona el siguiente código?

main()  
{  
   const int j=20;  
   int *p;  
   p=&j;  
   (*p)++;   
   return 0 ;  
} 

Este código funciona bien… ¿Cómo es posible cambiar una memoria de solo lectura? ¿Cómo se almacena realmente? Por favor explícamelo en detalle.

  • ¿Has revisado esto: stackoverflow.com/questions/3801557/… ?

    – Bojan Komazec

    25 de noviembre de 2010 a las 9:36

  • Puedo asegurarle que su segundo segmento de código es Comportamiento indefinido

    – SiegeX

    25 de noviembre de 2010 a las 9:41


  • Creo que la mayoría de los compiladores modernos darían una advertencia al pasar por la línea “p = & j” advirtiendo sobre diferentes calificadores const, porque está asignando un puntero a const int a un puntero a int. Entonces, la moraleja de la historia es: siempre use -Werror

    – hueso

    14 de marzo de 2016 a las 9:31

avatar de usuario
cody gris

la palabra clave const indica una variable que es de sólo lectura (es decir, no se puede cambiar en tiempo de ejecución). No indica una constante de tiempo de compilación. Por lo tanto, se aplican todos los atributos habituales de las variables; específicamente, se le asigna espacio de almacenamiento direccionable.

A diferencia de con #definetu constante no es necesariamente en línea por el compilador. Más bien, el compilador creará un símbolo correspondiente a su const declaración en el archivo de objeto para que se pueda acceder desde otros archivos de código, recuerde que const los objetos tienen enlaces externos de forma predeterminada en C (aunque algunos compiladores seguirán alineando el valor constante dentro del archivo donde se define).

La razón por la que el fragmento de código que publicaste “funciona” es porque el operador unario & se puede aplicar a cualquier lvalue, que incluye un const objeto. Aunque el comportamiento aquí no está definido, sospecho que su compilador detecta este uso y se asegura de que su const La declaración recibe un espacio de direcciones y, por lo tanto, no se inserta, ni siquiera dentro del archivo en el que se declara.

EDITAR: Ver también: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

Veamos qué significa cuando se usa const. Es bastante simple: const significa que algo no es modificable, por lo que un objeto de datos que se declara con const como parte de su especificación de tipo no debe asignarse de ninguna manera durante la ejecución de un programa. Es muy probable que la definición del objeto contenga un inicializador (de lo contrario, dado que no puede asignarlo, ¿cómo obtendría un valor?), Pero este no es siempre el caso. Por ejemplo, si estuviera accediendo a un puerto de hardware en una dirección de memoria fija y prometiera solo leer de él, entonces se declararía constante pero no inicializado.

Tomar la dirección de un objeto de datos de un tipo que no es const y ponerlo en un puntero a la versión calificada const del mismo tipo es seguro y está explícitamente permitido; podrá usar el puntero para inspeccionar el objeto, pero no modificarlo. Poner la dirección de un tipo const en un puntero al tipo no calificado es mucho más peligroso y, en consecuencia, está prohibido (aunque puede evitarlo usando un molde). Por ejemplo…

  • Esta es una respuesta genial. Solo entendí completamente lo que const significa en C cuando encontré una variable declarada const volatile (era un registro de hardware). Después de mi momento WTF inicial, me di cuenta de que const solo significa que usted, el programador, promete no cambiarlo. Si espera que cambie por otros medios, necesita la volatile. Pero el compilador no la interpreta como una constante de tiempo de compilación (como en C++Creo).

    – detly

    25 de noviembre de 2010 a las 9:47


  • @detly, una variable const no puede aparecer en un lugar donde se requiere sintácticamente una expresión constante (que de hecho está permitida para algunos de ellos en C++). El compilador aún puede considerarlo como una constante de tiempo de compilación para otros fines, y probablemente lo haga.

    – Un programador

    25 de noviembre de 2010 a las 10:18

  • @AProgrammer: de hecho, esa es una mejor redacción. Sin embargo, el compilador no puede considerarlo una constante de tiempo de compilación (o constante de tiempo de ejecución) si también se declara volátil.

    – detly

    25 de noviembre de 2010 a las 10:26

Modificando su código para imprimir el valor:

#include <stdio.h>

main()
{
   const int j=20;
   int *p;
   p=&j;
   (*p)++;
    printf("%d\n", j);
   return 0 ;
}

El código anterior, cuando se compila con gcc 4.3.2 en -O1 optimización o superior, da como resultado la salida 20 en vez de 21. Esto demuestra que en realidad no ha “funcionado”, simplemente apareció trabajar.

A const Calificatorio no es una solicitud para colocar la variable en un tipo particular de memoria: es una promesa de usted al compilador, que no modificará esa variable de ninguna manera. El compilador puede confiar en su promesa de optimizar el código que se produce, y si rompe su promesa, no necesariamente se romperá de una manera obvia, solo puede producir resultados extraños.

Según el estándar C (n1256 sequía):

6.7.3 Calificadores de tipo


3 Las propiedades asociadas con tipos calificados son significativas solo para expresiones que son valores l.114)


5 Si se intenta modificar un objeto definido con un tipo calificado const mediante el uso de un lvalue con un tipo no calificado const, el comportamiento no está definido. Si se intenta hacer referencia a un objeto definido con un tipo calificado como volátil mediante el uso de un valor l con un tipo calificado como no volátil, el comportamiento no está definido.115)


114) La implementación puede colocar un const objeto que no es volatile en una región de almacenamiento de solo lectura. Además, la implementación no necesita asignar almacenamiento para tal objeto si su dirección nunca se usa.

115) Esto se aplica a aquellos objetos que se comportan como si estuvieran definidos con tipos calificados, incluso si en realidad nunca se definen como objetos en el programa (como un objeto en una dirección de entrada/salida mapeada en memoria).

En resumen, un const-objeto calificado mayo almacenarse en un área diferente de la que noconst-objetos calificados, pero no necesariamente.

los const el calificador es una instrucción al compilador para rechazar el código que intenta modificar ese objeto directamente; los intentos de modificar el objeto indirectamente (como lo hace en el segundo fragmento de código) dan como resultado un comportamiento indefinido, lo que significa ninguna el resultado es posible.

No sé dónde está almacenado, porque está definido por la implementación, pero su código da como resultado un comportamiento indefinido.

Realmente no debería funcionar.

Las constantes generalmente no se almacenan en ninguna parte. Se expanden en línea.

Es posible que su compilador sea amable con usted y le dé una ubicación de memoria para modificar, pero normalmente eso es imposible.

¿Qué advertencias estás recibiendo? Me imagino que debes conseguir algo…

  • Se almacenan como cualquier otra variable, pero pueden ser reemplazadas por inline by Optimizer.

    – Vovanium

    25 de noviembre de 2010 a las 11:41

avatar de usuario
james anderson

Depende totalmente del escritor del compilador lo que suceda con la const, y variará según la optimización que solicite.

En su primer ejemplo, las constantes nunca se usan, por lo que el compilador probablemente las ignorará por completo.

En su segundo ejemplo, cuando usa “dirección desactivada”, en realidad debe almacenarlo en algún lugar, probablemente al comienzo de la pila.

Como C está diseñado para reemplazar las instrucciones del lenguaje ensamblador, y para escribir código de tipo de controlador de dispositivo y kernal del sistema operativo, le permite hacer todo tipo de cosas y asume que sabe lo que está haciendo cuando comienza a jugar con los punteros.

  • Se almacenan como cualquier otra variable, pero pueden ser reemplazadas por inline by Optimizer.

    – Vovanium

    25 de noviembre de 2010 a las 11:41

avatar de usuario
Integridad

El compilador determina si alguna vez se necesita la dirección de la constante. Si no es así, (generalmente) se ingresa en línea en el segmento de código porque eso es (generalmente) más rápido que hacer referencia a la memoria.

Si se necesita la dirección, la constante se almacena como si fuera una variable no constante en el ámbito actual (dependiendo relativamente del compilador). Es decir, las constantes globales generalmente se almacenan en su segmento de datos, las constantes de función (parámetro o declaradas) generalmente se almacenan en la pila.

Piense en ello como una variable de registro. Está en el registro de su CPU, si está familiarizado con eso. Está en el registro de su CPU hasta que necesite su dirección. Luego se coloca en un espacio direccionable.

La verdadera pregunta es la inicialización: si necesita su dirección y, por lo tanto, está realmente asignada, ¿dónde se inicializa? Hay algo para que usted reflexione.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad