Let's say I have this following bit of code in C:
double var;
scanf("%lf", &var);
printf("%lf", var);
printf("%f", var);
It reads from stdin variable 'var' and then prints twice in stdout 'var'.
I understand that's how you read a double variable from stdin, but my questions are:
Why can you print a double with %lf?
Why can you print a double with %f?
Which one is better and correct to use?
For variable argument functions like printf and scanf, the arguments are promoted, for example, any smaller integer types are promoted to int, float is promoted to double.
scanf takes parameters of pointers, so the promotion rule takes no effect. It must use %f for float* and %lf for double*.
printf will never see a float argument, float is always promoted to double. The format specifier is %f. But C99 also says %lf is the same as %f in printf:
C99 §7.19.6.1 The fprintf function
l (ell) Specifies that a following d, i, o, u, x, or X conversion specifier applies to a long int or unsigned long int argument; that a following n conversion specifier applies to a pointer to a long int argument; that a following c conversion specifier applies to a wint_t argument; that a following s conversion specifier applies to a pointer to a wchar_t argument; or has no effect on a following a, A, e, E, f, F, g, or G conversion specifier.
When a float is passed to printf, it is automatically converted to a double. This is part of the default argument promotions, which apply to functions that have a variable parameter list (containing ...), largely for historical reasons. Therefore, the “natural” specifier for a float, %f, must work with a double argument. So the %f and %lf specifiers for printf are the same; they both take a double value.
When scanf is called, pointers are passed, not direct values. A pointer to float is not converted to a pointer to double (this could not work since the pointed-to object cannot change when you change the pointer type). So, for scanf, the argument for %f must be a pointer to float, and the argument for %lf must be a pointer to double.
As far as I read manual pages, scanf says that 'l' length modifier indicates (in case of floating points) that the argument is of type double rather than of type float, so you can have 'lf, le, lg'.
As for printing, officially, the manual says that 'l' applies only to integer types. So it might be not supported on some systems or by some standards. For instance, I get the following error message when compiling with gcc -Wall -Wextra -pedantic
a.c:6:1: warning: ISO C90 does not support the ‘%lf’ gnu_printf format [-Wformat=]
So you may want to doublecheck if your standard supports the syntax.
To conclude, I would say that you read with '%lf' and you print with '%f'.
Related
Why is it that scanf() needs the l in "%lf" when reading a double, when printf() can use "%f" regardless of whether its argument is a double or a float?
Example code:
double d;
scanf("%lf", &d);
printf("%f", d);
Because C will promote floats to doubles for functions that take variable arguments. Pointers aren't promoted to anything, so you should be using %lf, %lg or %le (or %la in C99) to read in doubles.
Since С99 the matching between format specifiers and floating-point argument types in C is consistent between printf and scanf. It is
%f for float
%lf for double
%Lf for long double
It just so happens that when arguments of type float are passed as variadic parameters, such arguments are implicitly converted to type double. This is the reason why in printf format specifiers %f and %lf are equivalent and interchangeable. In printf you can "cross-use" %lf with float or %f with double.
But there's no reason to actually do it in practice. Don't use %f to printf arguments of type double. It is a widespread habit born back in C89/90 times, but it is a bad habit. Use %lf in printf for double and keep %f reserved for float arguments.
scanf needs to know the size of the data being pointed at by &d to fill it properly, whereas variadic functions promote floats to doubles (not entirely sure why), so printf is always getting a double.
Because otherwise scanf will think you are passing a pointer to a float which is a smaller size than a double, and it will return an incorrect value.
Using either a float or a double value in a C expression will result in a value that is a double anyway, so printf can't tell the difference. Whereas a pointer to a double has to be explicitly signalled to scanf as distinct from a pointer to float, because what the pointer points to is what matters.
I am currently learning about C language data type and I try to print a double variable the compiler suggested me to use fl after I type '%', and I got 1 number in the end of precision decimal line. Compare to %lf it will print six precision decimals in total
double num=12322;
printf("%lf",num);// result is 12322.000000
printf("%fl",num);// result is 12322.0000001
I've searched plenty of place but mostly the difference between %f and %lf is frequently asked. Is my situation could possiply the same?
In this call of printf
printf("%lf",num);// result is 12322.000000
the length modifier l in the conversion specifier %lf has no effect.
From the C Standard (7.21.6.1 The fprintf function)
7 The length modifiers and their meanings are:
l (ell) Specifies that a following d, i, o, u, x, or X conversion
specifier applies to a long int or unsigned long int argument; that a
following n conversion specifier applies to a pointer to a long int
argument; that a following c conversion specifier applies to a wint_t
argument; that a following s conversion specifier applies to a pointer
to a wchar_t argument; or has no effect on a following a, A, e, E,
f, F, g, or G conversion specifier.
In this call of printf
printf("%fl",num);// result is 12322.0000001
where in the comment there shall be written the letter 'l' instead of the number 1 as you think
// result is 12322.000000l
^^^
the format string "%fl" means that after outputting an object of the type double due to the conversion specification %f there will be outputted the letter 'l'.
Pay attention to that with the conversion specifier f there can be used one more letter 'l' that is the upper case letter 'L'. In this case the conversion specification %Lf serves to output objects of the type long double.
I think you actually have a typo in your output....
double num=12322;
printf("%lf",num);// result is 12322.000000
printf("%fl",num);// result is 12322.0000001
is actually
double num=12322;
printf("%lf",num);// result is 12322.000000
printf("%fl",num);// result is 12322.000000l
The C standard says that the float is converted to a double when passed to a variadic function, so %lf and %f are equivalent; %fl is the same a %f... with an l after it.
There are two correct ways of printing a value of type double:
printf("%f", num);
or
printf("%lf", num);
These two have exactly the same effect. In this case, the "l" modifier is effectively ignored.
The reason they have the same effect is that printf is special. printf accepts a variable number of arguments, and for such functions, C always applies the default argument promotions. This means that all integer types smaller than int are promoted to int, and float is promoted to double. So if you write
float f = 1.5;
printf("%f\n", f);
then f is promoted to double before being passed. So inside printf, it always gets a double. So %f will never see a float, always a double. So %f is written to expect a double, so it ends up working for both float and double. So you don't need a l modifier to say which. But that's kind of confusing, so the Standard says you can put the l there if you want to — but you don't have to, and it doesn't do anything.
(This is all very different, by the way, from scanf, where %f and %lf are totally different, and must be explicitly matched to arguments of type float * versus double *.)
I have no idea why your IDE complained about (put a red line under) %lf, and I have no idea what it meant by suggesting, as you said,
fl, lg, l, f,
elf, Alf, ls, sf,
if, la, lo, of
Some of those look they might be nonstandard, system-specific extensions, but some (especially fl) are nonsense. So, bottom line, it sounds like your IDE's suggestion was confusing, unnecessary, and quite possibly wrong.
Why is it that scanf() needs the l in "%lf" when reading a double, when printf() can use "%f" regardless of whether its argument is a double or a float?
Example code:
double d;
scanf("%lf", &d);
printf("%f", d);
Because C will promote floats to doubles for functions that take variable arguments. Pointers aren't promoted to anything, so you should be using %lf, %lg or %le (or %la in C99) to read in doubles.
Since С99 the matching between format specifiers and floating-point argument types in C is consistent between printf and scanf. It is
%f for float
%lf for double
%Lf for long double
It just so happens that when arguments of type float are passed as variadic parameters, such arguments are implicitly converted to type double. This is the reason why in printf format specifiers %f and %lf are equivalent and interchangeable. In printf you can "cross-use" %lf with float or %f with double.
But there's no reason to actually do it in practice. Don't use %f to printf arguments of type double. It is a widespread habit born back in C89/90 times, but it is a bad habit. Use %lf in printf for double and keep %f reserved for float arguments.
scanf needs to know the size of the data being pointed at by &d to fill it properly, whereas variadic functions promote floats to doubles (not entirely sure why), so printf is always getting a double.
Because otherwise scanf will think you are passing a pointer to a float which is a smaller size than a double, and it will return an incorrect value.
Using either a float or a double value in a C expression will result in a value that is a double anyway, so printf can't tell the difference. Whereas a pointer to a double has to be explicitly signalled to scanf as distinct from a pointer to float, because what the pointer points to is what matters.
I am writing a very small code just scanf and printf. I am reading a double value and printing it. The conversion specification %lf works properly to read a double value. But, it doesn't work with printf.
When I am trying to print that value I am getting output like 0.000000
double fag;
scanf("%lf", &fag);
printf("%lf", fag);
But, if I use %f in printf it works properly.
The C standard library implementation you're using doesn't conform to C99 (or newer). The changes listed in the foreword (paragraph 5) contain:
%lf conversion specifier allowed in printf
The description of the l length modifier is (C99+TC3 7.19.6.1 par. 7, emphasis mine):
Specifies that a following d, i, o, u, x, or X conversion specifier applies to a long int or unsigned long int argument; that a following n conversion specifier applies to a pointer to a long int argument; that a following c conversion specifier applies to a wint_t argument; that a following s conversion specifier applies to a pointer to a wchar_t argument; or has no effect on a following a, A, e, E, f, F, g, or G conversion specifier.
%f and %lf are therefore equivalent. Both expect a double because arguments matching the ellipsis (the ... in int printf(char const * restrict, ...);) undergo the so-called default argument promotions. Among other things they implicitly convert float to double. It doesn't matter for scanf() since pointers aren't implicitly converted.
So if you can't or don't want to update to a newer C standard library %f can always be used in a printf() format string to print float or double. However in scanf() format strings %f expects float* and %lf expects double*.
What is the correct format specifier for double in printf? Is it %f or is it %lf? I believe it's %f, but I am not sure.
Code sample
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
"%f" is the (or at least one) correct format for a double. There is no format for a float, because if you attempt to pass a float to printf, it'll be promoted to double before printf receives it1. "%lf" is also acceptable under the current standard -- the l is specified as having no effect if followed by the f conversion specifier (among others).
Note that this is one place that printf format strings differ substantially from scanf (and fscanf, etc.) format strings. For output, you're passing a value, which will be promoted from float to double when passed as a variadic parameter. For input you're passing a pointer, which is not promoted, so you have to tell scanf whether you want to read a float or a double, so for scanf, %f means you want to read a float and %lf means you want to read a double (and, for what it's worth, for a long double, you use %Lf for either printf or scanf).
1. C99, §6.5.2.2/6: "If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions." In C++ the wording is somewhat different (e.g., it doesn't use the word "prototype") but the effect is the same: all the variadic parameters undergo default promotions before they're received by the function.
Given the C99 standard (namely, the N1256 draft), the rules depend on the
function kind: fprintf (printf, sprintf, ...) or scanf.
Here are relevant parts extracted:
Foreword
This second edition cancels and replaces the first edition, ISO/IEC 9899:1990, as amended and corrected by ISO/IEC 9899/COR1:1994, ISO/IEC 9899/AMD1:1995, and ISO/IEC 9899/COR2:1996.
Major changes from the previous edition include:
%lf conversion specifier allowed in printf
7.19.6.1 The fprintf function
7 The length modifiers and their meanings are:
l (ell) Specifies that (...) has no effect on a following a, A, e, E, f, F, g, or G conversion specifier.
L Specifies that a following a, A, e, E, f, F, g, or G conversion specifier applies to a long double argument.
The same rules specified for fprintf apply for printf, sprintf and similar functions.
7.19.6.2 The fscanf function
11 The length modifiers and their meanings are:
l (ell) Specifies that (...) that a following a, A, e, E, f, F, g, or G conversion specifier applies to an argument with type pointer to double;
L Specifies that a following a, A, e, E, f, F, g, or G conversion
specifier applies to an argument with type pointer to long double.
12 The conversion specifiers and their meanings are:
a,e,f,g Matches an optionally signed floating-point number, (...)
14 The conversion specifiers A, E, F, G, and X are also valid and behave the same as, respectively, a, e, f, g, and x.
The long story short, for fprintf the following specifiers and corresponding types are specified:
%f -> double
%Lf -> long double.
and for fscanf it is:
%f -> float
%lf -> double
%Lf -> long double.
It can be %f, %g or %e depending on how you want the number to be formatted. See here for more details. The l modifier is required in scanf with double, but not in printf.
Format %lf is a perfectly correct printf format for double, exactly as you used it. There's nothing wrong with your code.
Format %lf in printf was not supported in old (pre-C99) versions of C language, which created superficial "inconsistency" between format specifiers for double in printf and scanf. That superficial inconsistency has been fixed in C99.
You are not required to use %lf with double in printf. You can use %f as well, if you so prefer (%lf and %f are equivalent in printf). But in modern C it makes perfect sense to prefer to use %f with float, %lf with double and %Lf with long double, consistently in both printf and scanf.
%Lf (note the capital L) is the format specifier for long doubles.
For plain doubles, either %e, %E, %f, %g or %G will do.