¿Cuál será su salida y por qué?

Estaba revisando las preguntas de las reglas de scope y todas y luego obtuve un fragmento de código, a continuación:

#include  int main() { int x = 1, y = 2, z = 3; printf(" x = %d, y = %d, z = %d \n", x, y, z); { int x = 10; float y = 20; printf(" x = %d, y = %f, z = %d \n", x, y, z); { int z = 100; printf(" x = %d, y = %f, z = %d \n", x, y, z); } } return 0; } 

Si cambio la última impresión a:

 printf("x = %d, y = %d, z = %d \n", x, y, z); 

Obtengo la siguiente salida, que no entiendo: (enlace Ideone)

 x = 10, y = 0, z = 1077149696 

Entonces, ¿podría explicar por qué z está imprimiendo ese valor?

x, y, yz se resuelven en la mayoría de las definiciones locales.

Cuando utiliza un especificador de printf% incorrecto, el comportamiento es indefinido.

y es flotante pero está utilizando% d para imprimirlo (en la línea posterior).

printf usa varargs y una vez que corrompe la stack utilizando un especificador incorrecto (% d en lugar de% f en este caso), la stack está dañada y la interpretación incorrecta de los datos de la stack (en un desplazamiento incorrecto) causaría muchas sorpresas dolorosas.

Decodificando esta UB

Esto es lo que podría estar sucediendo en su máquina (Una posible explicación). Debido a la promoción de argumentos predeterminada , el patrón de bits (en hexadecimal) 0x4034000000000000 se está empujando para astackr para 20.0f. Sizeof int en su máquina little-endian es de 4 bytes. Cuando imprime float como int, su máquina 0x00000000 se consume y se interpreta como int, que imprime primero 0 , luego %d consume 0x40340000, interpreta como int e imprime 1077149696. La final 100 (0x00000064) se deja sin astackr y la impresión regresa.

Pero nunca confíe en esto y siempre escriba un código para el cual el comportamiento esté bien definido.

@ mohit-jain es correcto.

El uso del especificador de formato incorrecto produce una interpretación de parámetros incorrecta en la stack, lo que resulta en un comportamiento indefinido y específico del comstackdor.

Tenga en cuenta que en un comstackdor moderno, como gcc o clang, se quejará de que su especificación de formato es incorrecta:

 $ clang test.c test.c:12:54: warning: format specifies type 'int' but the argument has type 'float' [-Wformat] printf(" x = %d, y = %d, z = %d \n", x, y, z); ~~ ^ %f 1 warning generated. 

z = 1077149696
Usar% d para imprimir valores flotantes es un comportamiento indefinido.
Utilice “% f” en su lugar

  1. Todas las variables que ha utilizado tienen un tipo de almacenamiento “Auto” o “Automático”.
  2. El scope de la variable automática se encuentra dentro del bloque en el que se declara.
  3. Si hay bloques nesteds, la variable declarada en el bloque más externo será visible para todos los otros bloques.
  4. En el caso de que un bloque tenga una variable declarada que coincida con la declarada en bloques externos, sobrescribirá la variable externa “en su bloque”, es decir (localmente).

En resumen: las variables automáticas son locales al bloque en el que se declaran.