2010-11-23 20 views
10

siguiente, la variable en el código no tiene valor inicial e imprimió esta variable.¿Por qué veo valores extraños cuando imprimo variables no inicializadas?

int var; 
cout << var << endl; 

de salida: 2514932

double var; 
cout << var << endl; 

de salida: 1.23769e-307

No entiendo este número de salida. ¿Puede alguien explicarme?

+2

Al compilar este código. ¿El compilador no genera muchas advertencias sobre variables no inicializadas? Si configura su compilador para tratar las advertencias como errores (una buena idea) y también aumenta el nivel de advertencia, entonces no compilará y creará un código más seguro (las advertencias suelen ser errores lógicos). –

+0

sí, compilo este código con gcc en ubuntu. no fue ninguna advertencia. – cmuse

+2

@cmuse - compilar con '-Wall', te ayudará a detectar más advertencias. Y este problema aparecerá una vez que use esa bandera. 'gcc -Wall source.c -o myexecutable' – birryree

Respuesta

0

que no se ha inicializado var en cualquiera de los casos para que pueda obtener la producción de basura.

que habían hecho

const int var(5);

que se inicializa con el valor 5

2

lo que está recibiendo es cualquier dato que pasó a ser en la pila en el lugar del compilador decidió que la variable debe ir interpretado como un entero o un doble. Probablemente será el mismo cada vez que se ejecute su programa porque los programas generalmente se comportan de manera determinista. Aunque también hay muchos casos en los que terminará siendo el mismo desde la ejecución de su programa. Si cambia su programa en lo más mínimo, o si toma decisiones basadas en los comentarios del usuario antes de llegar a ese código, puede o no obtener diferentes números.

Básicamente, el valor de una variable no se ha inicializado es indeterminado y puede ser cualquier cosa. No hay rima o razón para lo que hay allí.

Hacer esto es generalmente una mala práctica. Desea programas que se comporten de manera predecible, y tener variables no inicializadas es una fuente de imprevisibilidad. Tenga en cuenta que no es una fuente de aleatoriedad, simplemente imprevisibilidad. La mayoría de los compiladores se quejarán de un código como ese si activa todas las advertencias.

+0

Lo siento, pero no será lo mismo, incluso si el programa asigna el desplazamiento de la dirección de memoria de manera determinista, porque la memoria podría haber sido utilizada por algún otro programa o la dirección base de su programa puede haber cambiado. –

+0

@Bruno Brant - Esto es cierto. En muchos casos será lo mismo, y probablemente en el caso del OP. Pero debería actualizar mi respuesta con este detalle. – Omnifarious

30

En pocas palabras, var no se inicializa y la lectura de una variable no inicializada lleva a undefined behavior.

Así que no lo hacen. En el momento en que lo haga, ya no se garantiza que su programa hará lo que usted diga.


Formalmente, "leer" un valor significa realizar una conversión lvalue-r-value en él. Y §4.1 afirma "... si el objeto no está inicializado, un programa que necesita esta conversión tiene un comportamiento indefinido."

vista pragmático, que simplemente significa que el valor es basura (después de todo, es fácil ver la lectura de un int, por ejemplo, sólo se pone bits aleatorios), pero no podemos concluir esto, o estaríamos . definir un comportamiento indefinido

Para un ejemplo real, tenga en cuenta:

#include <iostream> 

const char* test() 
{ 
    bool b; // uninitialized 

    switch (b) // undefined behavior! 
    { 
    case false: 
     return "false";  // garbage was zero (zero is false) 
    case true: 
     return "true";  // garbage was non-zero (non-zero is true) 
    default: 
     return "impossible"; // options are exhausted, this must be impossible... 
    } 
} 

int main() 
{ 
    std::cout << test() << std::endl; 
} 

ingenuamente, uno podría concluir (a través del razonamiento en los comentarios) que esto nunca debe imprimir "impossible", pero con un comportamiento indefinido, todo es posible Compilarlo con g++ -02.

+2

+1 para la única respuesta técnicamente correcta hasta el momento – fredoverflow

+0

¿Está seguro de que los resultados no están definidos y no están definidos? La desreferenciación de un puntero no inicializado definitivamente no debe definirse, por supuesto. Pero, ¿no es solo no especificado qué valor tiene una variable no inicializada? – Omnifarious

+0

@Omni: He aclarado en la respuesta. – GManNickG

0

Cuando declara var se le asigna una ubicación en la memoria. Sin embargo, esa memoria no está configurada de manera predeterminada, por lo que puede recoger lo que haya antes. Este será un valor de basura que no tiene ningún significado.

En C++ esto es cierto tanto para las variables de miembros como para las variables locales. Sin embargo, en idiomas como Java y C# sus variables de miembro se inicializan automáticamente a 0 para tipos de números, falso para booleanos y nulo para referencias. Esto no se hace para las variables locales y (al menos en el compilador de C#) su compilación fallará si intenta tomar el valor de una variable no inicializada.

1

En C++, cuando declara una variable, el compilador le asigna una dirección de memoria. Y eso es todo, no se realiza ninguna limpieza. Esto se debe principalmente a C++ (y C) donde se construye teniendo en cuenta el rendimiento. C++ no pierde tiempo inicializando una dirección a menos que se lo indique explícitamente.

Y la llamada basura que ves es lo que quedó en esa dirección por la última variable que lo usó.

Otros idiomas inicializarán los datos por usted. De hecho, C# no le permitirá usar la variable hasta que la inicialice. Esos lenguajes están diseñados para ser seguros, en un sentido que no le permitirá escribir un código que utiliza una dirección no inicializada erróneamente y bloquear su programa o, lo que es peor, dañar sus datos.

Cuestiones relacionadas