2010-11-29 12 views
6

Mi comprensión de las variables estáticas declaradas dentro de una función es:Declarar una variable estática nivel de función dentro de un bloque if que nunca se golpeó

  1. Si no se especifica ningún valor inicial, la variable estática residirá en .bss, de lo contrario en .data
  2. la memoria para la estática se asignan junto con globals - es decir, mucho antes de la ejecución entra main
    • son estos dos supuestos correctos ?
  3. Cuando la ejecución realiza la función por primera vez, la estática se inicializan al valor especificado por el usuario (o cero en caso de que no se especifica ningún valor inicial).
  4. ... y conservan sus valores a través de invocaciones posteriores de la función

Pero lo que si me declaro mi variable estática dentro de un bloque de if? Supongo que mi tercer punto debe actualizarse al "cuando la ejecución llega a la línea donde se declara la variable estática, se inicializan en ..." - ¿estoy en lo cierto ?

Ahora, ¿qué pasa si el bloque if en el que se declaran nunca se golpea (y el compilador puede resolverlo)? Entiendo que la variable nunca se inicializará; pero, ¿se asigna algún recuerdo para esa variable?

escribí dos funciones para tratar de averiguar lo que está pasando:

#include <stdio.h> 

void foo() 
{ 
    static foo_var_out; 
    if(0){ 
     static foo_var_in_0; 
     printf("%d %d\n", foo_var_in_0); 
    } else { 
     static foo_var_in_1; 
     printf("%d %d\n", foo_var_in_1); 
    } 
} 

static void bar(int flag) 
{ 
    static bar_var_out; 
    if(flag){ 
     static bar_var_in_0; 
     printf("%d %d\n", bar_var_in_0); 
    } else { 
     static bar_var_in_1; 
     printf("%d %d\n", bar_var_in_1); 
    } 
} 

int main() 
{ 
    foo(); 
    bar(0); 
} 

y yo tomamos el volcado de objeto:

$ gcc -o main main.c 
$ objdump -t main | grep var 
45:080495c0 l  O .bss 00000004    foo_var_in_1.1779 
46:080495c4 l  O .bss 00000004    foo_var_out.1777 
47:080495c8 l  O .bss 00000004    bar_var_in_1.1787 
48:080495cc l  O .bss 00000004    bar_var_in_0.1786 
49:080495d0 l  O .bss 00000004    bar_var_out.1785 

Desde la salida se ve como foo_var_in_0 no fue creada en absoluto (presumiblemente porque está dentro de un explícito if(0)), mientras que bar_var_in_0 fue creado (ya que es posible que la persona que llama pase un valor distinto de cero, aunque el único que llama pasa explícitamente cero).

Supongo que mi pregunta es: ¿es correcto suponer que no se asignó memoria para la variable foo_var_in_0 en absoluto? Estoy preguntando sobre este caso específico; ¿Estoy leyendo el objdump correctamente, o debería estar haciendo algo más para verificar si la variable tomará algo de memoria mientras se ejecuta el programa?

En otras palabras, si la línea que declara una variable estática nivel de función no se ve afectado, es en realidad la variable declarada en absoluto?

Si no se creará en absoluto, es esto de acuerdo con el estándar C (menos probable), o una optimización de tiempo de compilación y en qué nivel - cómo lo enciendo/apaga (en gcc 4.1.1) ?

Entiendo que una int no es un gran problema que preocuparse, pero estoy más interesado en cómo funciona; Además, ¿qué pasaría si la variable tuviera una gran variedad de tamaños, digamos 5000 elementos de una estructura de 10 bytes?

+0

ambos son creados por mí: http://pastebin.com/6cRbHWMJ (gcc MinGW 4.5.1) – Kos

Respuesta

3

¿Es correcto suponer que no se asignó memoria para la variable foo_var_in_0 en absoluto?

No, no creo que sea correcto suponer eso. Hasta donde yo sé, las optimizaciones de este tipo no son parte del estándar.

Si sabe con certeza que su compilador hace esto y desea asumirlo, continúe. Si escribe algo que necesita que este sea el caso, puede escribir una prueba posterior a la construcción para asegurarse de que sucedió.

Probablemente, lo que está viendo es un efecto secundario del compilador que simplemente borra algún código que sabía que nunca funcionaría. Es decir, no busca específicamente eliminar estáticas, pero eliminó una rama completa, por lo que cualquier código que allí se eliminó también.

+0

Basado en los datos de objdump en este caso específico (comprendo que no es prudente confiar en eso, pero para confirmar que estoy leyendo objdump correctamente), puedo suponer sin temor a dudas que no se ha reservado espacio para esa variable. ¿Es eso correcto? ¿O hay algo más que deba hacer para verificar si la variable tendrá memoria mientras se ejecuta? – Amarghosh

+0

Creo que lees objdump correctamente y que la estática nunca fue asignada. Creo que en este caso, para este compilador, en esta compilación, puede suponer que no se dejó espacio. No puede suponer que sea el caso para el futuro a menos que continúe verificándolo. –

+0

Gracias, y entiendo el mensaje; no voy a confiar en este comportamiento :) – Amarghosh

2

El estándar C no prescribe dónde colocar las variables y esas cosas.Simplemente prescribe que una implementación conforme debe tener un comportamiento equivalente (a un comportamiento de referencia especificado por el estándar), donde el estándar también define "equivalente".

Así que la respuesta simple es que es una optimización, y cómo activarla/desactivarla depende del compilador en particular.

Una implementación que hace análisis interprocedurales probablemente también podría deshacerse de bar_var_in_0.

+0

Eso tiene más sentido - es la eliminación llanura de código no alcanzados - nada específico a la electricidad estática. – Amarghosh

2

Solo para agregar a las respuestas correctas de los demás. Sus suposiciones sobre la inicialización de las variables static no son correctas.

  • Las variables con almacenamiento estático son siempre inicializadas. O explícitamente si proporciona un inicializador o implícitamente desde 0.
  • El inicializador para dicha variable debe ser siempre una expresión constante de tiempo de compilación . Por lo tanto, el valor es calculado en tiempo de compilación y escrito directamente en el objeto. (Bueno, si es es todos cero, algunos sistemas tienen trucos secciones especiales/que eviten un almacenamiento explícito de la variable en el archivo objeto.)
  • Así que no, no habrá inicializador ejecución declaración cuando el variable es accedido la primera vez (¿cómo saber el sistema sabe, por el valor de otra variable estática?) pero cada vez que inicia el programa la variable es ya inicializada.
+0

Gracias - No sabía que el inicializador debe ser una constante de tiempo de compilación. – Amarghosh

Cuestiones relacionadas