2011-03-23 9 views
9

¿Puede explicar la salida de este programa C? Supongo que el problema es que la pila se está dañando durante la llamada a la función printf("%d\n",t); porque estoy presionando un float pero leyendo un int. No estoy seguro.Resultado inesperado en el programa C

#include <stdio.h> 

int main() 
{ 
    long x; 
    float t; 
    scanf("%f",&t); 
    printf("%d\n",t); 
    x=30; 
    printf("%f\n",x); 
    { 
     x=9; 
     printf("%f\n",x); 
     { 
      x=10; 
      printf("%f\n",x); 
     } 
     printf("%f\n",x); 
    } 
    x==9; 
    printf("%f\n",x); 

} 

Y la salida

$ ./a.out 
20.39 
0 
20.389999 
20.389999 
20.389999 
20.389999 
20.389999 
$ 
+2

Necesita compilar su código con más advertencias de compilación habilitadas, y preste atención a las advertencias que le da (antes de publicar el código en SO). –

+1

@Jonathan Leffler: Al leer la Q, él sabe que lo está haciendo mal, pero me gustaría entender lo que realmente sucede. Sin embargo, debería haber sido más explícito e incluir información de compilador/plataforma. – Erik

Respuesta

1

Está utilizando el especificador de formato incorrecto para imprimir larga. Use el especificador de formato %ld en su lugar. Results

printf("%f\n",x); 
    //^change this to %ld 
+0

sé que está mal, pedí una explicación para la salida. Gracias de todos modos. – svpranay

+0

el uso del especificador de formato incorrecto puede llevar a cualquier cosa como cita @Prasoon establecida en el estándar. De ahí el resultado. – Mahesh

9

Lo que pasa es que mientas el compilador ... primero le dice que se va a enviar un int de printf, pero le envíe un flotador en su lugar, y luego te diga que se va a envíe un double pero envíe un long en su lugar.

No hagas eso. No mientas al compilador.

Usted ha invocado comportamiento indefinido. Cualquier cosa puede suceder. Tu programa podría corromper la pila; puede dar salida a lo que esperas; podría hacer que el jugo de limón salga del puerto USB; podría hacer demons fly out of your nose; ...

0

printf("%d\n",t);

Usando especificador de formato incorrecto en printf invoca un comportamiento indefinido.

Uso %f para imprimir float y double y %ld para la impresión de larga

C99 dice claramente (WRT printf y fprintf)

Si una conversión especí fi cación no es válido, el comportamiento es nidas inde fi. Si algún argumento es no es el tipo correcto para la especificación de conversión correspondiente, el comportamiento es indefinido.

1

Lo que en realidad sucede es:

  • Su float es de 4 bytes, el long es de 4 bytes, el double es de 8 bytes.
  • Usted pasa un float mediante puntos suspensivos - se convierte en double. 8 bytes en la pila.
  • Usted pasa un long mediante puntos suspensivos - 4 bytes en la pila.
  • printf analiza 8 bytes en la pila (float especificador) como double. Este double consistirá en la parte "importante" de la antigua double en la pila, y una ligera variación en la parte menos significativa (su long).
  • Predeterminado %f salida trunca el valor, no ve la variación.

Cambie todo %f a p. %.20f para ver cómo el long afecta al double.

+0

En AMD64 los primeros ocho argumentos 'float' se pasan a través de registros SSE, por lo que' long' no sobrescribirá ni siquiera una parte. – aaz

+0

@aaz: El comportamiento coincide con x86, así que estoy haciendo algo malo y supongo :) – Erik

+0

- Concuerda con AMD64, así que estoy asumiendo que también :) El resultado '% .20f' será diferente. – aaz

Cuestiones relacionadas