Comportamiento variable no inicializado en C ++

Me he revisado a mí mismo, escribí un progtwig como este

int main() { int i; cout << i; return 0; } 

Ejecuté el progtwig varias veces y el resultado fue el mismo todo el tiempo, cero. Lo probé en C y el resultado fue el mismo.

Pero mi libro de texto dice

Si no inicializa una variable definida dentro de una función, el valor de la variable permanece indefinido. Esto significa que el elemento toma el valor que residía previamente en esa ubicación en la memoria.

¿Cómo es posible cuando el progtwig siempre asigna una ubicación de memoria libre a una variable? ¿Cómo podría ser algo en lugar de cero (supongo que el valor de memoria libre predeterminado es cero)?

¿Cómo es posible cuando el progtwig siempre asigna una ubicación de memoria libre a una variable? ¿Cómo podría ser algo en lugar de cero?

Echemos un vistazo a una implementación práctica de ejemplo.

Digamos que utiliza la stack para mantener variables locales.

 void foo(void) { int foo_var = 42; } void bar(void) { int bar_var; printf("%d\n", bar_var); } int main(void) { bar(); foo(); bar(); } 

El código completamente roto anterior ilustra el punto. Después de llamar a foo, cierta ubicación en la stack donde se colocó foo_var se establece en 42. Cuando llamamos a la barra, bar_var ocupa esa ubicación exacta. Y, de hecho, la ejecución del código da como resultado la impresión de 0 y 42, que muestra que no se puede confiar en el valor de bar_var a menos que se inicialice.

Ahora debe quedar claro que se requiere inicialización de variable local. Pero, ¿podría ser una excepción? ¿Hay algo que pueda jugar con la stack y, en consecuencia, darnos un valor distinto de cero?

Sí. main no es la primera función ejecutada en su progtwig . De hecho, se requieren toneladas de trabajo para configurar todo. Cualquiera de este trabajo podría haber usado la stack y dejar algunos no ceros en ella. No solo no puede esperar el mismo valor en diferentes sistemas operativos, de repente puede cambiar en el sistema que está utilizando en este momento. Las partes interesadas pueden buscar “enlazador dynamic” en google.

Finalmente, el estándar de lenguaje C ni siquiera tiene el término stack. Tener un “lugar” para las variables locales se deja al comstackdor. Incluso podría ser basura al azar de lo que sea que ocurra en un registro dado. Realmente puede ser cualquier cosa . De hecho, si se desencadena un comportamiento indefinido, el comstackdor tiene libertad para hacer lo que quiera.

Si no inicializa una variable definida dentro de una función, el valor de la variable permanece indefinido.

Este bit es verdad

Eso significa que el elemento toma el valor que residía previamente en esa ubicación en la memoria.

Este bit no es

Algunas veces en la práctica esto ocurrirá, y usted debe darse cuenta de que obtener cero o no obtener el cero se ajusta perfectamente a esta teoría, para cualquier ejecución dada de su progtwig.

En teoría, su comstackdor podría asignarle un valor inicial aleatorio a ese entero si así lo deseara, por lo que tratar de racionalizarlo es completamente inútil. Pero continuemos como si asumiéramos que “el elemento toma el valor que residía previamente en esa ubicación en la memoria” …

¿Cómo podría ser algo en lugar de cero (supongo que el valor de memoria libre predeterminado es cero)?

Bueno, esto es lo que sucede cuando asumes. 🙂

Las variables estáticas y las variables globales se inicializan a cero:

 Global: int a; //a is initialized as 0 void myfunc(){ static int x; // x is also initialized as 0 printf("%d", x);} 

Donde como variables no estáticas o variables automáticas , es decir, las variables locales son indeterminadas (indeterminado generalmente significa que puede hacer cualquier cosa. Puede ser cero, puede ser el valor que estaba allí, puede bloquear el progtwig). Leerlos antes de asignar un valor da como resultado un comportamiento indefinido.

 void myfunc2(){ int x; // value of x is assigned by compiler it can even be 0 printf("%d", x);} 

En su mayoría depende del comstackdor, pero en general la mayoría de los casos el valor es asumido como 0 por los cumplidores

Este código invoca comportamiento no definido (UB), ya que el puntero se utiliza sin inicializar.

El comstackdor debería emitir una advertencia, cuando se usa una bandera de advertencia, como -Wall por ejemplo:

 warning: 'i' is used uninitialized in this function [-Wuninitialized] cout << i; ^ 

Simplemente sucede que en esta ejecución, en su sistema, tenía el valor de 0. Eso significa que el valor de basura al que se le asignó la variable, pasó a ser 0, porque los rests de memoria allí sugeridos así.

Sin embargo, tenga en cuenta que, los ceros del núcleo aparecen con relativa frecuencia . Eso significa que es bastante común que pueda obtener cero como salida de mi sistema, pero no está garantizado y no debe tomarse como una promesa.