c - Resultado inesperado de printf
casting garbage (4)
int a=5;
float b=3.5;
printf("%d",b);
printf("/n%f",a);
¿Alguien puede decirme por qué este código muestra resultados inesperados (basura / n3.5)?
Debido a que la variable es un tipo int, mientras que usted está especificando una cadena de formato para un tipo de letra flotante, y viceversa para la variable b
.
Nota :
%d
es para tipo entero
%f
es para tipo de flotador
Deberías usar :
int a=5;
float b=3.5;
printf("%f",b);
printf("/n%d",a);
Está pasando un float
para la cadena de formato %d
, pero printf
espera una int
.
printf
es una función de lista de argumentos variable: printf(const char *format_string,...);
Esto significa que el resto de los argumentos posteriores a la cadena de formato pueden ser de cualquier tipo y número, y el compilador no sabe qué deberían ser. Depende del programador proporcionar argumentos que sean del tipo que printf
espera. Lo que printf
espera está determinado por la cadena de formato. Cuando da un %d
en su cadena de formato, la función printf esperará que el siguiente argumento sea un int
. Como pasas float
, es probable que algo extraño suceda. Por ejemplo, esos bytes que componen el número de punto flotante se pueden tratar como si fueran un int
, lo que no le dará ningún valor significativo.
En realidad, es un poco más complicado que eso. Existen reglas especiales sobre cómo se pasan los parámetros a las funciones de argumento variable. Una de las reglas es que los valores float
se pasan como double
. Lo que significa que su valor float
primero se convierte en un double
antes de pasarse a printf
. Lo más probable es que un double
sea ocho bytes en su plataforma, mientras que un int
es solo cuatro. Entonces, la función printf
podría tratar los primeros cuatro bytes de su double
valor como int
.
Lo que es incluso peor es que en la siguiente línea, se está pasando un int
donde se espera un double
. Lo que significa que la función printf
podría tratar los primeros cuatro bytes de tu int
como parte del double
, y luego leer cuatro bytes más que ni siquiera formaban parte de tus argumentos.
Los detalles de lo que realmente ocurre son específicos de la plataforma. El lenguaje simplemente indica que no debe pasar el tipo de argumento incorrecto y no garantiza que sucederá si lo hace.
Formato error incorrecto de cadena, de acuerdo con sus declaraciones de b
:
printf("%d",b); <-- "b is float" Wrong!
printf("/n%f",a); <-- "a is an int" Wrong! -- Undefined behavior
debiera ser:
printf("%f",b);
printf("/n%d",a);
P: ¿Por qué estás obteniendo esa salida?
Se debe a un comportamiento indefinido de tu código:
De ESTÁNDAR INTERNACIONAL © ISO / IEC ISO / IEC 9899: 201x
7.16.1 Macros de acceso a la lista de argumentos variables
(página 270)
7.16.1.1 La macro
va_arg
[...] Si no hay un próximo argumento real, o si el tipo no es compatible con el tipo del siguiente argumento real (como se promueve de acuerdo con las promociones del argumento predeterminado), el
behavior is undefined
, excepto en los siguientes casos:
- un tipo es unsigned integer type
, el otro es el tipounsigned integer
correspondiente, y el valor es representable en ambos tipos;
- un tipo es puntero avoid
y el otro es un puntero a un tipo de carácter
int main()
{
int a=5;
float b=3.5;
printf("%f",b); //Use %f
printf("/n%d",a); // Use %d
}
Consulte: printf
El especificador de formato incorrecto para printf
lleva un comportamiento indefinido en la mayoría de los casos.
Sin embargo, dado que printf
es una función variadica, y los argumentos para funciones variadic se someten al molde de argumento predeterminado. Al igual, un char se convierte en un int.