2009-10-16 32 views
40

Me pregunto dónde se almacenan las variables constantes. En la misma área de memoria que las variables globales? ¿O en la pila?¿Dónde se almacenan las variables constantes en C?

+2

Me pregunto qué gramática es esta ... – DevSolar

+1

Esta pregunta no tiene sentido. Por favor reformula. – nall

+3

I * intenté * reformular la pregunta. Espero tener la intención del OP correctamente. – DevSolar

Respuesta

37

Cómo se almacenan es un detalle de implementación (depende del compilador).

Por ejemplo, en el compilador de GCC, en la mayoría de las máquinas, las variables de solo lectura, las constantes y las tablas de salto se colocan en la sección de texto.

+3

Esta es probablemente la única respuesta verdadera (aunque sería más útil proporcionar métodos de implementación populares después de señalar esto). –

+0

Simplemente indicar "detalles de implementación", aunque es correcto, puede que no sea la "mejor" respuesta aquí. Supongo que se trataba de un curioso principiante, y como tal, el desafío aquí es descubrir y responder: "Creo que quisiste preguntar * esto * y, como tal, creo que quieres leer * que *". – Mizipzor

+1

@Lee: si se trata de "implementación definida", cualquiera que dependa de "métodos de implementación populares" significa que su código podría fallar en la próxima actualización del compilador. Lamentablemente, esto no es entendido por todos, por lo que muchos de los que sí lo entienden no "proporcionan" información sobre implementaciones particulares, con la esperanza de que los tipos que no entienden tengan la pista ... – DevSolar

1

Normalmente se almacenan en la sección de datos de solo lectura (mientras que la sección de variables globales tiene permisos de escritura). Por lo tanto, intentar modificar la constante tomando su dirección puede dar como resultado una violación de acceso también conocida como segfault.

Pero realmente depende de su hardware, sistema operativo y compilador.

+2

"Por lo tanto, intentar modificar la constante tomando su dirección puede dar como resultado una violación de acceso, también conocida como segfault". Oh, si solo eso fuera cierto aquí en OS X. Simplemente lo probé, y funciona increíblemente. –

+0

en Windows, p. funciona solo para algunos compiladores. p.ej. VC++ y gcc generan ese código, pero uno de Borland no (al menos no lo hicieron la última vez que los usé, las cosas pueden haber cambiado). –

+0

Cuando trato de modificar la variable global const, obtengo un error de violación de acceso (ya que la variable se almacena en el segmento de datos de solo lectura). Pero puedo modificar la variable const local ya que la variable se almacena en la pila. – siva

1

Esto es principalmente una suposición educada, pero yo diría que las constantes generalmente se almacenan en las instrucciones reales de la CPU de su programa compilado, como datos inmediatos. En otras palabras, la mayoría de las instrucciones incluyen espacio para que la dirección obtenga datos, pero si es una constante, el espacio puede contener el valor mismo.

3

Depende de su compilador, las capacidades de su sistema, su configuración durante la compilación.

gccputs constantes de solo lectura en la sección .text, a menos que se indique lo contrario.

0

Global y constante son dos palabras clave completamente separadas. Puedes tener uno o el otro, ninguno o ambos.

Donde su variable, entonces, se almacena en la memoria depende de la configuración. Lea un poco sobre heap y stack, que le dará algunos conocimientos para hacer más preguntas (y si se puede, mejor y más específicas).

11

Considere el código:

const int i = 0; 
static const int k = 99; 

int function(void) 
{ 
    const int j = 37; 
    totherfunc(&j); 
    totherfunc(&i); 
    //totherfunc(&k); 
    return(j+3); 
} 

Generalmente, i se pueden almacenar en el segmento de texto (que es una de sólo lectura variable con un valor fijo). Si no está en el segmento de texto, se almacenará junto a las variables globales. Dado que se inicializa a cero, podría estar en la sección 'bss' (donde generalmente se asignan variables cerradas) o en la sección 'datos' (donde las variables inicializadas suelen asignarse).

Si el compilador está convencido de que el k no está en uso (que podría ser porque es local en un único archivo), es posible que no aparezca en el código del objeto. Si la llamada a totherfunc() que hace referencia a k no se ha comentado, entonces k debería tener asignada una dirección en algún lugar; probablemente estaría en el mismo segmento que i.

La constante (si es una constante, ¿sigue siendo una variable?) j probablemente aparecerá en la pila de una implementación C convencional. (Si estuviera preguntando en el grupo de noticias comp.std.c, alguien mencionaría que el estándar no dice que las variables automáticas aparecen en la pila; afortunadamente, SO no es comp.std.c!)

Tenga en cuenta que obligué a las variables a aparecer porque las pasé por referencia, presumiblemente a una función que espera un puntero a un entero constante. Si las direcciones nunca se tomaron, entonces j y k podrían optimizarse completamente fuera del código.Para eliminar i, el compilador debería conocer todo el código fuente de todo el programa: se puede acceder a él en otras unidades de traducción (archivos fuente) y, por lo tanto, no se puede eliminar fácilmente. Doblemente, no, si el programa se entrega a la carga dinámica de bibliotecas compartidas, una de esas bibliotecas puede depender de esa variable global.

(Estilísticamente - las variables ij y deben tener más tiempo, nombres más significativos; esto es sólo un ejemplo!)

+0

"(si es una constante, ¿sigue siendo una variable?)" Por definición, no. –

+1

'j' seguramente puede verse como una variable. La palabra "variable" no está definida en 'C', pero en C++' j' es una variable. 'variable' es simplemente un objeto con nombre, ya sea const o no. En C, los literales y los enumeradores se llaman 'constantes' - no creo que' j' se llame una "constante" en C, también porque no puede aparecer en expresiones constantes. –

0

Algunas constantes arfen't incluso almacenados.

Considere el siguiente código: int x = foo(); x *= 2;. Lo más probable es que el compilador cambie la multiplicación a x = x+x; ya que eso reduce la necesidad de cargar el número 2 de la memoria.

+0

...o a una multiplicación constante, donde los 2 serían almacenados en la instrucción de la CPU real –

+0

"Algunas constantes incluso no ..." deberían ser "no son" (lo habría editado pero por alguna razón no puedo cambia menos de 6 caracteres: /) – Rptk99

0

Puede que no se almacene en absoluto.

Considere algunas código como este:

#import<math.h>//import PI 
double toRadian(int degree){ 
    return degree*PI*2/360.0; 
} 

Esto permite al programador para recoger la idea de lo que está pasando, pero el compilador puede optimizar la distancia algo de eso, y la mayoría de los compiladores hacen, mediante la evaluación de expresiones constantes en tiempo de compilación, lo que significa que el valor PI puede no estar en absoluto en el programa resultante.

25

En función de la segmentación de datos que sigue a un procesador en particular, que tienen cinco segmentos: Segmento

  1. Código - tiendas sólo código, ROM
  2. BSS (o bloque Iniciado por símbolos) Segmento - Tiendas inicializado mundial y las variables estáticas
  3. segmento
  4. Pila - almacena todos los varialbles locales y otras informaciones relativas a la función de dirección de retorno, etc
  5. segmento de Heap - todas las asignaciones dinámicas que sucede aquí
  6. segmento de datos - venta no inicializadas las variables globales y estáticas

Tenga en cuenta que la diferencia entre el BSS y el segmento de datos es que los primeros tienda inicializado varialbes globales y estáticas y las tiendas a finales de los sin inicializar.

Ahora, ¿Por qué estoy hablando de la segmentación de datos que hacen obligatoria la diciéndole a donde son constantes las variables almacenadas ... hay una razón para ello ...

Cada segmento tiene una región protegida de escritura donde todos las constantes están almacenadas.

Por ejemplo,

si tengo un int const que es variable local, a continuación, se almacena en la región de escritura protegida de segmento de pila. y si tengo un global que se inicializa const var, entonces se almacena en BSS y si tengo un const var no inicializado, entonces se almacena en el segmento de datos ...

Para resumir, "const" es solo una QUALIFIER de datos, lo que significa que primero el compilador debe decidir qué segmento debe almacenarse la variable y luego si la variable es const, entonces califica para ser almacenada en la región de escritura protegida de ese segmento en particular.

Espero que esto aclare la mayoría de los malentendidos ....:-)

más comentarios son bienvenidos ... :-)

+19

"y si tengo un global que se inicializa const var, entonces se almacena en BSS y si tengo un const var no inicializado, entonces se almacena en el segmento de datos ..." .. Creo que debería ser como unificado -> bss, inicializado -> segmento de datos – Subbu

+2

"si tengo un const int que es una variable local, entonces se almacena en la región protegida de escritura del segmento de pila". ¿Qué parte de la pila está protegida contra escritura? – jimis

+3

El segmento de datos tiene 2 partes: Initialzed y unificado. BSS -> segmento de datos no inicializados. – Mayank

1
offcourse no

, porque

1) segmento bss almacena las variables no inilized obviamente otro tipo está ahí.

variables de
 (I) large static and global and non constants and non initilaized variables it stored .BSS section. 

     (II) second thing small static and global variables and non constants and non initilaized variables stored in .SBSS section this included in .BSS segment. 

2) segmento de datos se initlaized que tiene 3 tipos,

 (I) large static and global and initlaized and non constants variables its stord in .DATA section. 
     (II) small static and global and non constant and initilaized variables its stord in .SDATA1 sectiion. 
    (III) small static and global and constant and initilaized OR non initilaized variables its stord in .SDATA2 sectiion. 

i menciono anteriormente medios pequeños y grandes depents sobre compilador por ejemplo medios pequeños < de 8 bytes y grandes medios> que 8 bytes e iguales valores.

pero mi duda es la constante local ¿dónde se expandirá ??????

0

Como complemento, como usted sabe que es durante el proceso de vinculación se decide la memoria del último ejecutable. Hay una sección más llamada COMÚN en la que se colocan los símbolos comunes de diferentes archivos de entrada. la sección común realmente cae bajo la sección .bss.

Cuestiones relacionadas