¿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);

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.


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.


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.


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.


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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.