2009-12-02 23 views
10

Quiero saber por qué exactamente las variables estáticas en C, C++ y Java se inicializan por cero de forma predeterminada? ¿Y por qué esto no es cierto para las variables locales?¿Inicialización de variable estática?

+0

¿De qué idioma estás hablando? – Justin

+0

¿No es específico del lenguaje, pero se trata de conceptos? En todos los lenguajes C, C++, Java, la inicialización predeterminada de la variable estática es cero –

+0

No, Ton, las variables estáticas se inicializan por defecto. – GManNickG

Respuesta

19

¿Por qué las variables estáticas se inicializan determinísticamente y las variables locales no?

Vea cómo se implementan las variables estáticas. La memoria para ellos se asigna al momento del enlace, y el valor inicial para ellos también se proporciona en el tiempo del enlace. No hay sobrecarga de tiempo de ejecución.

Por otro lado, la memoria para variables locales se asigna en tiempo de ejecución. La pila tiene que crecer. No sabes lo que estaba allí antes. Si lo desea, puede borrar esa memoria (ponerla a cero), pero eso podría generar una sobrecarga de tiempo de ejecución. La filosofía de C++ es "no paga por cosas que no usa", por lo que no se borra esa memoria de manera predeterminada.

Bien, pero ¿por qué las variables estáticas se inicializan a cero, y no algún otro valor?

Bueno, generalmente quiere hacer algo con esa variable. Pero ¿cómo sabes si se ha inicializado? Puede crear una variable booleana estática. Pero luego también debe ser inicializado de manera confiable a algo (preferiblemente falso). ¿Qué tal un puntero? Preferirías que se inicializara a NULL que una basura aleatoria. ¿Qué tal una estructura/registro? Tiene algunos otros miembros de datos adentro. Tiene sentido inicializarlos todos a sus valores predeterminados. Pero para simplificar, si usa la estrategia "inicializar a 0", no tiene que inspeccionar a los miembros individuales y verificar sus tipos. Puede inicializar toda el área de memoria a 0.

Esto no es realmente un requisito técnico. La semántica de la inicialización podría considerarse sana si el valor predeterminado es distinto de 0, pero aún es determinista. Pero entonces, ¿cuál debería ser ese valor? Puede explicar fácilmente por qué se usa 0 (aunque de hecho suena un poco arbitrario), pero explicar -1 o 1024 parece ser aún más difícil (especialmente que la variable puede no ser lo suficientemente grande como para mantener ese valor, etc.).

Y siempre puede inicializar la variable explícitamente.

Y siempre tiene el párrafo 8.5.6 de la norma C++ que dice "Todos los objetos de la duración del almacenamiento estático se inicializarán en cero al inicio del programa".

Para obtener más información, por favor refiérase a estas otras preguntas:

+0

sí Estoy de acuerdo en que la memoria de las variables estáticas está asignada en el tiempo del enlace, pero por qué es cero por defecto. –

+0

Expandí mi respuesta, espero que tenga la información que le interesa. –

+0

¿Qué pasa con un objeto de clase, seguro de que su constructor no se llamará en el momento del enlace, y luego, si se inicializa en tiempo de enlace, simplemente se inicializa como un POD, que parece no tener sentido? –

4

El párrafo 8.5.6 de la norma indica que C++:

"Cada objeto de la duración de almacenamiento estático será inicializado a cero al inicio del programa"

(La norma también dice que la inicialización de las variables locales es indefinido)

En cuanto a por qué, la norma no lo dice;) Una suposición es que es razonablemente fácil de implementar sin inconvenientes adicionales.

+0

Probablemente quiera saber por qué se tomó esta decisión. – GManNickG

+0

Sí, eso es cierto, pero mi pregunta es ¿por qué? –

+0

Y la otra cara es que la inicialización predeterminada de los locales generaría un golpe de rendimiento. Y los diseñadores de C++ están más centrados en el rendimiento que en la facilidad para escribir programas correctos. –

3

Hablando para Java:

variables locales deben inicializarse antes de poder acceder a él, porque es un aumento de la seguridad. El compilador busca por usted, si la variable está definitivamente configurada.

variables estáticas o de clase (con un tipo de objeto) se inicializan con null, porque el compilador no puede verificar si se inicializan en tiempo de compilación. En lugar de dejar que el programa falle si accede a una variable no inicializada, se inicializará implícitamente con null.

Las variables con un tipo nativo no pueden obtener un valor null, por lo que las variables no locales se inicializan con 0 o false, por si falla. No es la mejor solución, claro, pero no conozco una mejor. ;-)

+0

En realidad, desde el punto de vista JVM, la variable local simplemente no existe hasta que se inicializa. – Buhb

+1

El compilador comprueba que los campos finales están asignados y no obviamente utilizados antes de asignarse. Sin embargo, todavía hay formas de ver los campos antes de las asignaciones (no es cierto para los locales). Los campos estáticos no finales deben ser extremadamente raros (* debe *). Deja abierto por qué no se considera un error probable dejar un campo con el valor predeterminado. –

+1

@Tom - La respuesta a su pregunta "abierta" es que sería extremadamente difícil crear reglas de JLS para esto que 1) no requieran el análisis de todas las clases en un programa, y ​​2) hagan frente a la carga dinámica. –

0

Esto es sólo una suposición, pero podría ser la forma en que es estática, ya que es fácil de implementar y útil.

El compilador puede asignar todas las variables en un área de memoria contigua, y luego o bien emitir código (una sola llamada a memset()) para borrarlo antes de llamar al main(). En muchos casos también puede depender de características de formato de archivo ejecutable del sistema operativo, si ese formato compatible "bss sections", que se eliminan por el cargador en su lugar. Esto ahorra espacio en el ejecutable, usted podría tener

static unsigned char megabyte[1 << 20]; 

y el ejecutable no aumentaría en un megabyte.

Para las variables locales, ninguna de estas opciones se aplica: se asignan "sobre la marcha" (normalmente en una pila) y sería un desperdicio de recursos borrarlas, ya que Normalmente, vamos a asignar muy pronto.

1

No tengo ni idea de Java y lo dudo es diferente para estáticos/locales en java.

En cuanto a c y C++, se trata de que los programadores se preocupen por el efecto del código y les encanta tener el control. La inicialización de variables locales implicaría la ejecución de código adicional cada vez que el programa ingrese al alcance. Para funciones frecuentemente llamadas que pueden ser un desastre.

+0

Bien escrito, pero esa no es una respuesta a mi pregunta –

+0

No estoy seguro de lo que quiere. Si rechaza esto, esperaría que aceptara la respuesta de Andreas. Él cita el estándar y te doy la razón detrás de esto. ¿Qué respuesta estás buscando? –

+0

Esto supone que los compiladores son realmente tontos.En casi todos los casos, es fácil ver si se asigna una variable antes del uso. –

2

Hasta cierto punto, estas son solo decisiones de diseño por parte de los diseñadores de idiomas.Pero las razones probables de estas decisiones en Java son:

  • para las variables estáticas/miembros, si se va a inicializar a algo, entonces el cero es un valor conveniente porque (a) por lo general es un valor adecuado a significa "no establecido en otra cosa especial", y es el valor que habría elegido de todos modos en algunos casos, como los contadores; y (b) internamente, es probable que cero se pueda usar para valores "especiales", especialmente para representar nulo en el caso de una referencia de objeto.
  • para las variables locales, no darles ningún valor predeterminado permite la regla que obliga al programador a establecer algún valor antes de leer la variable, lo que en realidad puede ser útil para permitir que el compilador detecte ciertos errores.

En el caso de las variables locales, también es concebible que una variable local podría ser declarada (que a nivel de código/máquina de código de bytes en esencia significa la asignación de espacio de pila/mover el puntero de pila), pero luego en realidad nunca escrito/leído en una ruta de código particular. Por lo tanto, no tener un valor predeterminado evita hacer un trabajo innecesario para establecer un valor predeterminado en esos casos.

Repito, sin embargo, estas son decisiones de diseño hasta cierto punto. Básicamente se trata de una compensación entre lo que probablemente sea conveniente para las implementaciones de JVM y conveniente para los programadores.

N. B. En C/C++, las variables "estáticas" significan algo diferente a las variables estáticas en Java.

1

Esto tiene que ver con el concepto de "sólo paga por lo que usa" en C/C++.

Para variables estáticas, se puede realizar una inicialización sin generar código. El archivo objeto contiene los valores iniciales para las variables en el segmento de datos y cuando el sistema operativo carga el archivo ejecutable, carga y mapea este segmento de datos antes de que el programa comience a ejecutarse.

Para las variables locales no hay forma de inicializarlas sin código porque no se inicializan una sola vez, deben inicializarse cada vez que ingrese su alcance; también se asignan en la pila, y cuando se produce la asignación, el valor inicial en la pila en el caso general es simplemente lo que estaba allí antes (excepto esos raros momentos en los que crece la pila más de lo que creció anteriormente).

Para inicializar implícitamente una variable local, el compilador necesitaría generar código sin que el programador se lo ordene explícitamente, lo cual es bastante contrario a esa "filosofía".

Acerca de Java, hasta donde yo sé, las variables siempre se inicializan cuando el programa entra en su alcance, no importa si son estáticas o no. La única diferencia significativa entre ellos es que el alcance de las variables estáticas es el programa completo. Dado que, el comportamiento es constante entre todos ellos.

Cuestiones relacionadas