¿Por qué scanf () necesita "% lf" para los dobles, cuando printf () está bien con solo "% f"?

179

¿Por qué scanf()necesita el l" %lf" cuando lee un double, cuándo printf()puede usar " %f" independientemente de si su argumento es a doubleo a float?

Código de ejemplo:

double d;
scanf("%lf", &d);
printf("%f", d);
raldi
fuente
1
No entiendo lo que quieres decir con POINTER aquí. En scanf solo pasamos una dirección variable (es decir), entonces, ¿dónde está el puntero
77
@deetchanya En C, cuando "toma la dirección de" una variable con el &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 pasa scanf.
zwol
Esta es otra publicación sobre este stackoverflow.com/questions/9291348/…
vimalpt

Respuestas:

207

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, %lgo %le(o %laen C99) para leer en dobles.

MSN
fuente
26

Desde С99, la coincidencia entre los especificadores de formato y los tipos de argumento de coma flotante en C es consistente entre printfy scanf. Es

  • %f para float
  • %lf para double
  • %Lf para long double

Sucede que cuando los argumentos de tipo floatse pasan como parámetros variables, dichos argumentos se convierten implícitamente en tipo double. Esta es la razón por la cual en printflos especificadores de formato %fy %lfson equivalentes e intercambiables. En printfusted puede "uso cruzado" %lfcon floato %fcon double.

Pero no hay razón para hacerlo en la práctica. No utilice %fa printfargumentos de tipo double. Es un hábito generalizado nacido en C89/90 veces, pero es un mal hábito. Uso %lfen printfpara doubley mantenga %freservada para floatlos argumentos.

Hormiga
fuente
1
Diría que usar %fen printf es un buen hábito porque su código siempre funciona, mientras que usarlo %lfpuede fallar si el compilador no tiene una biblioteca compatible con C99. Lamentablemente, esa situación sucede en la realidad.
MM
Desde С99, la coincidencia entre los especificadores de formato y los tipos de argumento de coma flotante en C es consistente entre printfy scanf. 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 formato scanf()que se utilizó por printf()lo que no lea correctamente los datos. Por ejemplo, el relleno del espacio que puede ser insertado por un prinf()'s "%d"especificador de formato se omitirá por el mismo "%d"especificador de formato en una scanf()llamada.
Andrew Henle
16

scanfnecesita saber el tamaño de los datos a los que apunta &dpara llenarlos correctamente, mientras que las funciones variadas promueven flotantes a dobles (no del todo seguro por qué), por printflo que siempre se obtiene un double.

Tanktalus
fuente
1
Una función variadic es muy frágil, porque necesita poder saber el tipo y el tamaño exactos de todos los parámetros que se le pasan, y no puede aplicar esto en tiempo de compilación. Si una variable es del tipo incorrecto, se leerá el valor incorrecto; si es del tamaño incorrecto, todas las variables posteriores también se leerán mal. Si se pudieran pasar dos tamaños diferentes de flotador, causaría todo tipo de problemas desagradables y fáciles de perder.
mwfearnley
7

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.

Jim Buck
fuente
2

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.

fcw
fuente
55
float se convierte en doble en este caso porque los argumentos son parte de una lista de argumentos de longitud variable, los flotantes no siempre se convierten en dobles en C.
Robert Gamble,
1
En versiones pre-estándar de lenguaje C, los floatvalores se promocionaban automáticamente doubleen expresiones. Esa regla se abandonó en el estándar C. Generalmente, floatno se promueve doubleen expresiones. Solo se promueve doublecuando se pasa como un argumento variado, que es lo que sucede en este caso.
2015