Especificador de formato correcto para doble en printf


482

¿Cuál es el especificador de formato correcto para doubleprintf? ¿Es %fo es %lf? Creo que es %f, pero no estoy seguro.

Muestra de código

#include <stdio.h>

int main()
{
   double d = 1.4;
   printf("%lf", d); // Is this wrong?
}

19
Si está atascado con una biblioteca C89, "%lf"no está definido; en las bibliotecas C99 y C11 se define como igual que "%f".
pmg

1
Su variante es tan correcta como siempre. %lfes el especificador de formato correcto para double. Pero se hizo así en C99. Antes de eso tenía que usar %f.
ANT

Respuestas:


626

"%f"es el formato correcto (o al menos uno) para un doble. No es ningún formato para una float, ya que si se intenta pasar una floata printf, que va a ser promovido a doubleantes de printfla recibe 1 . "%lf"también es aceptable según el estándar actual: lse especifica que no tiene efecto si es seguido por el fespecificador de conversión (entre otros).

Tenga en cuenta que este es un lugar que printflas cadenas de formato difieren sustancialmente de scanf(e fscanf, etc.) las cadenas de formato. Para la salida, está pasando un valor , que se promocionará de floatadouble cuando se pasa como parámetro variadic. Para la entrada estás pasando un puntero , que no se promueve, por lo que tiene que decir scanfsi desea leer un floato una double, así que para scanf, %fmedios que desea leer una floaty %lfmedios que desea leer una double(y, por lo que es vale la pena, por un long double, que utiliza %Lfpara cualquiera printfo scanf).


1. C99, §6.5.2.2 / 6: "Si la expresión que denota la función llamada tiene un tipo que no incluye un prototipo, las promociones de enteros se realizan en cada argumento, y los argumentos que tienen tipo flotante se promueven a doble. Estos se denominan promociones de argumento predeterminadas ". En C ++, la redacción es algo diferente (p. Ej., No usa la palabra "prototipo") pero el efecto es el mismo: todos los parámetros variables se someten a promociones predeterminadas antes de ser recibidos por la función.


8
Tenga en cuenta que g++rechaza %lfal compilar con -Wall -Werror -pedantic:error: ISO C++ does not support the ‘%lf’ gnu_printf format
kynan

2
@kynan: Si es así (al menos suponiendo una versión actual de g ++), eso es un error en g ++. Para C89 / 90 y C ++ 98/03, permitir lera una extensión. Los estándares C99 / 11 y C ++ 11 requieren la implementación para permitirlo.
Jerry Coffin

1
Curiosamente, scanf hace falta doubles representada por %lf: se queja de que se espera float *y se encontró double *con sólo %f.
Eric Dand

1
@JerryCoffin g ++ sigue siendo el modo predeterminado de g ++ 98
MM

55
@EricDand Eso es porque scanflleva los punteros a dónde almacenar lo que lee, por lo que necesita saber qué tan grande es el espacio al que se apunta, mientras que printftoma los valores en sí mismos y las "promociones de argumento predeterminadas" significan que ambos terminan como doubles, por lo que les esencialmente opcional.
TripeHound

63

Dado el estándar C99 (es decir, el borrador N1256 ), las reglas dependen del tipo de función: fprintf (printf, sprintf, ...) o scanf.

Aquí se extraen las partes relevantes:

Prefacio

Esta segunda edición cancela y reemplaza la primera edición, ISO / IEC 9899: 1990, según enmendada y corregida por ISO / IEC 9899 / COR1: 1994, ISO / IEC 9899 / AMD1: 1995 e ISO / IEC 9899 / COR2: 1996. Los principales cambios de la edición anterior incluyen:

  • %lf especificador de conversión permitido en printf

7.19.6.1 La fprintffunción

7 Los modificadores de longitud y sus significados son:

l (ell) Especifica que (...) no tiene efecto en un siguiente especificador de conversión a, A, e, E, f, F, g o G.

L Especifica que el siguiente especificador de conversión a, A, e, E, f, F, g o G se aplica a un argumento doble largo.

Las mismas reglas especificadas para fprintfsolicitar printf, sprintfy funciones similares.

7.19.6.2 La fscanffunción

11 Los modificadores de longitud y sus significados son:

l (ell) Especifica que (...) que el siguiente especificador de conversión a, A, e, E, f, F, g o G se aplica a un argumento con puntero de tipo a doble;

L Especifica que el siguiente especificador de conversión a, A, e, E, f, F, g o G se aplica a un argumento con puntero de tipo a doble largo.

12 Los especificadores de conversión y sus significados son: a, e, f, g Coincide con un número de punto flotante opcionalmente firmado, (...)

14 Los especificadores de conversión A, E, F, G y X también son válidos y se comportan igual que, respectivamente, a, e, f, gy x.

La larga historia corta, para fprintflos siguientes especificadores y tipos correspondientes se especifican:

  • %f -> doble
  • %Lf -> largo doble.

y por fscanfeso es:

  • %f -> flotador
  • %lf -> doble
  • %Lf -> largo doble.

25

Puede ser %f, %go %edependiendo de cómo desee que se formatee el número. Ver aquí para más detalles. El lmodificador se requiere scanfcon double, pero no con printf.


1
-1: el lmodificador (en minúsculas) es para tipos enteros ( cplusplus.com/reference/clibrary/cstdio/printf ), y Les para tipos de punto flotante. Además, el Lmodificador espera un long double, no un plano double.
user470379

10
user470379: Entonces, ¿dónde está la contradicción con mi respuesta? No he dicho que lno se requiere printfpara double.
Vitaut

16

El formato %lfes un printfformato perfectamente correcto double, exactamente como lo usó. No hay nada malo con tu código.

El formato %lfen printfno era compatible con las versiones antiguas (anteriores a C99) del lenguaje C, lo que creaba una "inconsistencia" superficial entre los especificadores de formato para doublein printfy scanf. Esa inconsistencia superficial se ha solucionado en C99.

No es obligatorio usarlo %lfcon doublein printf. También puede usar %f, si así lo prefiere ( %lfy %fson equivalentes printf). Pero en la C moderna tiene mucho sentido preferir usar %fcon float, %lfcon doubley %Lfcon long double, consistentemente en ambos printfy scanf.


Con scanf(), "%f", "%lf"coincida con una float *, double *, no float, doublecomo se deduce de la última línea.
chux - Restablecer Monica

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.