2010-07-13 26 views
21
#include <stdio.h> 
int main() { 
    int c = c; 
    printf("c is %i\n", c); 
    return 0; 
} 

Estoy definiendo una variable entera llamada c, y estoy asignando su valor a sí mismo. Pero, ¿cómo puede esto incluso compilar? c no se ha inicializado, entonces, ¿cómo se puede asignar su valor a sí mismo? Cuando ejecuto el programa, obtengo c is 0.¿Por qué compila este código C?

Supongo que el compilador está generando código de ensamblado que está asignando espacio para la variable c (cuando el compilador encuentra la instrucción int c). Luego toma el valor no deseado que esté en ese espacio no inicializado y lo vuelve a asignar al c. ¿Esto es lo que está pasando?

+3

Desafortunadamente, está permitido: normalmente puede hacer que el compilador emita una advertencia al respecto, por ejemplo, al usar g ++ (pero no gcc por algún motivo) al utilizar el indicador -Wall produce una advertencia. –

+7

@Neil, para forzar un error con gcc, utiliza '-Werror = uninitized -Winit-self' –

Respuesta

30

Recuerdo citar esto en una respuesta anterior, pero no puedo encontrarlo en este momento.

C++ 03 §3.3.1/1:

El punto de la declaración de un nombre es inmediatamente después de su completa declarador (cláusula 8) y antes de su inicializador (si lo hay), ...

Por lo tanto, la variable c se puede utilizar incluso antes de la parte del inicializador.

Edit: Disculpe, usted ha preguntado acerca de C específicamente; aunque estoy seguro de que hay una línea equivalente allí. James McNellis lo encontró:

C99 §6.2.1/7: Cualquier identificador que no sea una estructura, unión o etiqueta de enumeración "tiene alcance que comienza justo después de la finalización de su declarador". El declarador es seguido por el inicializador.

+0

Spot on! '+ 1' ....... –

+0

¡Gracias! Excelente explicación! –

+12

C99 §6.2.1/7: cualquier identificador que no sea una estructura, unión o etiqueta de enumeración "tiene un alcance que comienza justo después de la finalización de su declarador". El declarador es seguido por el inicializador. –

2

c se ha inicializado!

Aunque esta es una línea de código, de hecho, inicializa c primero, y luego le asigna c. Tienes suerte de que el compilador inicialice c a cero para ti.

+0

-1 ...equivocado e incorrecto, pero aún votó más alto ... la variable 'c' en el ejemplo que se muestra no es un puntero, sino que está asignado en la pila. – gnud

+4

¿Qué? ¿Quién dijo que tenía que ser un puntero? –

+1

No estoy de acuerdo: 'c' no está inicializado para mí (según las opciones del compilador), lo que se evidencia por una salida distinta de cero cuando se ejecuta este código. – pilcrow

5

Es un comportamiento indefinido utilizar un valor no inicializado (§C99 J.2 "El valor de un objeto con una duración de almacenamiento automático se utiliza mientras que es indeterminado"). Entonces, cualquier cosa puede pasar de nasal demons a c = 0, a playing Nethack.

+0

El valor es indeterminado, pero ese no es un comportamiento indefinido. Los demonios nasales y Nethack están fuera. c = 0 es posible (y probable). El comportamiento aquí se define de forma similar a un generador de números aleatorios en el sentido de que, si bien no podemos determinar el valor resultante, podemos garantizarnos con el estándar que el valor es lo único desconocido sobre esta afirmación. –

11

Su suposición es exactamente correcta. int c empuja espacio en la pila para la variable, que luego se lee y se vuelve a escribir para la parte c = c (aunque el compilador puede optimizar eso). Su compilador está presionando el valor como 0, pero esto no siempre está garantizado.

+0

+1 Bien explicado. –

+4

Es probable que no presione 0, simplemente sucede que el marco de pila existente ya contiene 0 de memoria. Dependiendo de 0, hay, por supuesto, indefinido. –

+0

+1 ¡Muy útil! –

2

La especificación C no garantiza que las variables se inicialicen en 0, 0.0 ni "" o "".

Esa es una característica de compiladores y nunca debe empujar eso sucederá.

Siempre configuro mi IDE/compilador como advertencia al respecto.

Cuestiones relacionadas