Especificador de formato correcto para doble en printf
¿ Cuál es el especificador de formato correcto double
en printf? ¿Es %f
o es %lf
? Creo que lo es %f
, pero no estoy seguro.
Ejemplo de código
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
"%f"
es el (o al menos uno) formato correcto para un doble. No hay formato para a float
, porque si intenta pasar a float
, printf
será promovido a double
antes de printf
recibirlo 1 . "%lf"
también es aceptable según el estándar actual: se l
especifica que no tiene efecto si va seguido del f
especificador de conversión (entre otros).
Tenga en cuenta que este es un lugar donde printf
las cadenas de formato difieren sustancialmente de las cadenas de formato scanf
(y fscanf
, etc.). Para la salida, está pasando un valor , que se promoverá de float
a double
cuando se pase como parámetro variado. Para la entrada, está pasando un puntero , que no se promociona, por lo que debe indicar scanf
si desea leer a float
o a double
, por lo que for significa que desea leer a y significa que desea leer a (y, por lo que es vale, para a , usas para o o ).scanf
%f
float
%lf
double
long double
%Lf
printf
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 float se promueven a doble. Éstas se denominan promociones de argumentos predeterminados". En C++ la redacción es algo diferente (por ejemplo, no usa la palabra "prototipo") pero el efecto es el mismo: todos los parámetros variados se someten a promociones predeterminadas antes de que la función los reciba.
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 partes relevantes:
Prefacio
Esta segunda edición cancela y reemplaza la primera edición, ISO/IEC 9899:1990, modificada y corregida por ISO/IEC 9899/COR1:1994, ISO/IEC 9899/AMD1:1995 e ISO/IEC 9899/COR2:1996. Los principales cambios con respecto a la edición anterior incluyen:
%lf
especificador de conversión permitido enprintf
7.19.6.1 La
fprintf
función7 Los modificadores de longitud y sus significados son:
l (ell) Especifica que (...) no tiene ningún efecto en el 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.
Se aplican las mismas reglas especificadas fprintf
para printf
y sprintf
funciones similares.
7.19.6.2 La
fscanf
función11 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 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 long double.
12 Los especificadores de conversión y sus significados son: a,e,f,g Coincide con un número de punto flotante con signo opcional, (...)
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, g y x.
En pocas palabras, fprintf
se especifican los siguientes especificadores y los tipos correspondientes:
%f
-> doble%Lf
-> doble largo.
y para fscanf
ello es:
%f
-> flotar%lf
-> doble%Lf
-> doble largo.