¿Por qué las variables estáticas se inicializan automáticamente a cero?

Posible duplicado:
¿Por qué las variables globales y estáticas se inicializan a sus valores predeterminados?

¿Cuál es la razón técnica por la que sucede esto? ¿Y es compatible con el estándar en todas las plataformas? ¿Es posible que ciertas implementaciones puedan devolver variables no definidas si las variables estáticas no se inicializan explícitamente?

Es requerido por la norma (§6.7.8 / 10).

No hay ninguna razón técnica por la que deba ser así, pero ha sido así durante tanto tiempo que el comité estándar lo convirtió en un requisito.

Dejar de lado este requisito haría que el trabajo con variables estáticas sea más difícil en muchos (¿la mayoría?) Casos. En particular, a menudo tiene que realizar una inicialización única y necesita un estado de inicio confiable para saber si una variable en particular se ha inicializado o no. Por ejemplo:

int foo() { static int *ptr; if (NULL == ptr) // initialize it } 

Si ptr pudiera contener un valor arbitrario en el inicio, tendría que inicializarlo explícitamente en NULL para poder reconocer si ya realizó la inicialización única o no.

Sí, es porque está en la norma; Pero en realidad, es porque es gratis. Las variables estáticas se parecen a las variables globales del código objeto generado. Se asignan en .bss y se inicializan en el tiempo de carga junto con todas sus constantes y otras variables globales. Dado que la sección de la memoria donde viven se copia directamente desde su ejecutable, se inicializan en un valor conocido en tiempo de comstackción de forma gratuita. El valor elegido fue 0.

Por supuesto, no hay argumento de que esté en los estándares C. Así que espera que un comstackdor compatible se comporte de esa manera.

La razón técnica detrás de por qué se hizo podría estar enraizada en cómo funciona el código de inicio de C. Por lo general, hay varios segmentos de memoria en los que el enlazador debe incluir la salida del comstackdor para incluir un segmento de código (texto), un segmento de almacenamiento de bloques y un segmento variable inicializado.

Las variables de función no estáticas no tienen almacenamiento físico hasta que el scope de la función se crea en tiempo de ejecución, por lo que el vinculador no hace nada con ellas.

El código del progtwig, por supuesto, va en el segmento de código (o texto) pero también lo hacen los valores utilizados para inicializar variables globales y estáticas. Las variables inicializadas en sí mismas (es decir, sus direcciones) van en el segmento de memoria inicializado. Las variables globales y estáticas no inicializadas van en el segmento de almacenamiento de bloques (bss).

Cuando el progtwig se carga en el momento de la ejecución, un pequeño fragmento de código crea el entorno C runtime. En los sistemas basados ​​en ROM, copiará el valor de las variables inicializadas del segmento de código (texto) en sus respectivas direcciones reales en la RAM. Los sistemas basados ​​en RAM (es decir, disco) pueden cargar los valores iniciales directamente en las direcciones de RAM finales.

El CRT (tiempo de ejecución de C) también pone a cero el bss que contiene todas las variables globales y estáticas que no tienen inicializadores. Esto probablemente se hizo como una precaución contra los datos no inicializados. Es una operación de relleno de bloque relativamente sencilla porque todas las variables globales y estáticas se han agrupado en un segmento de dirección.

Por supuesto, los flotantes y los dobles pueden requerir un manejo especial, ya que su valor de 0.0 puede que no sea del todo cero si el formato flotante no es IEEE 754.

Tenga en cuenta que, dado que las autovariables no existen en el momento de la carga del progtwig, el código de inicio del tiempo de ejecución no las puede inicializar.

Sobre todo porque las variables estáticas están agrupadas en un bloque por el vinculador, por lo que es muy fácil simplemente memset () todo el bloque a 0 en el inicio. No creo que sea requerido por los Estándares C o C ++.

Hay discusión sobre esto aquí :

En primer lugar, en ISO C (ANSI C), todas las variables estáticas y globales deben inicializarse antes de que comience el progtwig. Si el progtwigdor no hizo esto explícitamente, entonces el comstackdor debe ponerlos a cero. Si el comstackdor no hace esto, no sigue la norma ISO C. Sin embargo, la norma no especifica exactamente cómo se inicializan las variables.

Eche un vistazo: aquí 6.2.4 (3) y 6.7.8 (10)

Supongamos que estuvieras escribiendo un comstackdor de C. Usted espera que algunas variables estáticas tengan valores iniciales, por lo que esos valores deben aparecer en algún lugar del archivo ejecutable que su comstackdor creará. Ahora, cuando se ejecuta el progtwig de salida, el archivo ejecutable completo se carga en la memoria. Parte de la inicialización del progtwig es crear las variables estáticas, por lo que todos esos valores iniciales deben copiarse en sus destinos finales de variables estáticas.

¿O ellos? Una vez que se inicia el progtwig, los valores iniciales de las variables ya no son necesarios. ¿No se pueden ubicar las variables dentro del código ejecutable? Entonces no hay necesidad de copiar los valores. Las variables estáticas podrían vivir dentro de un bloque que estaba en el archivo ejecutable original, y no se debe hacer ninguna inicialización para ellas.

Si ese es el caso, ¿por qué querría hacer un caso especial para variables estáticas sin inicializar? ¿Por qué no solo poner un montón de ceros en el archivo ejecutable para representar las variables estáticas no inicializadas? Eso cambiaría algo de espacio por un poco de tiempo y mucha menos complejidad.

No sé si algún comstackdor de C realmente se comporta de esta manera, pero sospecho que la opción de hacer las cosas de esta manera podría haber impulsado el diseño del lenguaje.