¿Por qué scanf()
necesita el l
" %lf
" cuando lee un double
, cuándo printf()
puede usar " %f
" independientemente de si su argumento es a double
o a float
?
Código de ejemplo:
double d;
scanf("%lf", &d);
printf("%f", d);
c
scanf
length-modifiers
raldi
fuente
fuente
&
operador unario , el resultado de esa operación es un puntero a la ubicación de almacenamiento de la variable en la memoria. Es ese puntero al que se pasascanf
.Respuestas:
Porque C promoverá flotantes a dobles para funciones que toman argumentos variables. Los punteros no se promocionan a nada, por lo que debería usar
%lf
,%lg
o%le
(o%la
en C99) para leer en dobles.fuente
Desde С99, la coincidencia entre los especificadores de formato y los tipos de argumento de coma flotante en C es consistente entre
printf
yscanf
. Es%f
parafloat
%lf
paradouble
%Lf
paralong double
Sucede que cuando los argumentos de tipo
float
se pasan como parámetros variables, dichos argumentos se convierten implícitamente en tipodouble
. Esta es la razón por la cual enprintf
los especificadores de formato%f
y%lf
son equivalentes e intercambiables. Enprintf
usted puede "uso cruzado"%lf
confloat
o%f
condouble
.Pero no hay razón para hacerlo en la práctica. No utilice
%f
aprintf
argumentos de tipodouble
. Es un hábito generalizado nacido en C89/90 veces, pero es un mal hábito. Uso%lf
enprintf
paradouble
y mantenga%f
reservada parafloat
los argumentos.fuente
%f
en printf es un buen hábito porque su código siempre funciona, mientras que usarlo%lf
puede fallar si el compilador no tiene una biblioteca compatible con C99. Lamentablemente, esa situación sucede en la realidad.printf
yscanf
. Tenga en cuenta que esto no implica que el uso del mismo especificador de formato signifique que los datos escritos por a[f]printf()
puedan ser leídos[f]scanf()
. En general, el uso de la misma para el especificador de formatoscanf()
que se utilizó porprintf()
lo que no lea correctamente los datos. Por ejemplo, el relleno del espacio que puede ser insertado por unprinf()
's"%d"
especificador de formato se omitirá por el mismo"%d"
especificador de formato en unascanf()
llamada.scanf
necesita saber el tamaño de los datos a los que apunta&d
para llenarlos correctamente, mientras que las funciones variadas promueven flotantes a dobles (no del todo seguro por qué), porprintf
lo que siempre se obtiene undouble
.fuente
Porque, de lo contrario, scanf pensará que está pasando un puntero a un flotante que tiene un tamaño menor que el doble, y devolverá un valor incorrecto.
fuente
El uso de un valor flotante o doble en una expresión en C dará como resultado un valor que sea doble de todos modos, por lo que printf no puede notar la diferencia. Mientras que un puntero a un doble tiene que ser señalado explícitamente para scanf a diferencia de un puntero para flotar, porque lo que apunta el puntero es lo que importa.
fuente
float
valores se promocionaban automáticamentedouble
en expresiones. Esa regla se abandonó en el estándar C. Generalmente,float
no se promuevedouble
en expresiones. Solo se promuevedouble
cuando se pasa como un argumento variado, que es lo que sucede en este caso.