Problems with scanf and doubles [duplicate] - c

This question already has answers here:
Why does scanf() need "%lf" for doubles, when printf() is okay with just "%f"?
(5 answers)
Closed 8 years ago.
im having trouble understanding why this occurs:
with the following code;
#include <stdio.h>
int main()
{
double x=123;
printf("x is %f. Enter a new value for x.\n", x);
scanf("%f", &x);
printf("x is %f\n", x);
return 0;
}
when you enter 45678 as the new value for x, 'x is 123.000017' is printed.
I know that this is fixed when you use %lf when scanning, but why does this happen when using %f?

I know that this is fixed when you use %lf when scanning, but why does this happen when using %f?
The difference between printf and scanf function arguments is that you pass values to printf, but to scanf you pass pointers (i.e. addresses of values). According to C rules, when a function takes a variable number of arguments, all parameters undergo default promotions.
One of the promotions is that floats get converted to double, in the same way that shorts get converted to int. That is why you can use %f or %lf with printf: both types of values are converted by the compiler to double, so accessing them is safe.
However, there is no such rule for pointers (and for a good reason: trying to write a double into a space of float would be undefined behavior). That is why you must differentiate between %f and %lf when passing parameters to the scanf family of functions.

scanf("%f", &x);
should be
scanf("%lf", &x);
There is a false symmetry for floating points conversion specifiers between printf and scanf.
Also note that lf conversion specifier is equivalent to f conversion specifier in printf (since c99, it was undefined before).
I know that this is fixed when you use %lf when scanning, but why does this happen when using %f?
f conversion specifier in scanf requires an argument of type pointer to float. By passing an argument of type pointer to double you invoke undefined behavior.

Related

Anyone know why this code always returns 33.80? [duplicate]

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.

Strange behavior when reading and writing "float" and "double" types in C [duplicate]

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.

Why the division of two integers return 0.00? [duplicate]

This question already has answers here:
printf("%f", aa) when aa is of type int [duplicate]
(2 answers)
Closed 7 years ago.
Every time I run this program I get different and weird results. Why is that?
#include <stdio.h>
int main(void) {
int a = 5, b = 2;
printf("%.2f", a/b);
return 0;
}
Live Demo
printf("%.2f", a/b);
The output of the division is again of type int and not float.
You are using wrong format specifier which will lead to undefined behavior.
You need to have variables of type float to perform the operation you are doing.
The right format specifier to print out int is %d
In your code, a and b are of type int, so the division is essecntially an integer division, the result being an int.
You cannot use a wrong format specifier anytime. %f requires the corresponding argument to be of type double. You need to use %d for int type.
FWIW, using wrong format specifier invokes undefined behaviour.
From C11 standard, chapter §7.21.6.1, fprintf()
If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
If you want a floating point division, you need to do so explicitly by either
promoting one of the variable before the division to enforce floating point division, result of which will be of floating point type.
printf("%.2f", (float)a/b);
use float type for a and b.
You need to change the type as float or double.
Something like this:
printf("%.2f", (float)a/b);
IDEONE DEMO
%f format specifier is for float. Using the wrong format specifier will lead you to undefined behavior. The division of int by an int will give you an int.
Use this instead of your printf()
printf("%.2lf",(double)a/b);

How integers numbers are printed with %f specifier? [duplicate]

This question already has answers here:
Unexpected output of printf
(4 answers)
Closed 9 years ago.
#include<stdio.h>
main()
{
int a = 66;
printf("%f", a);
}
It is printing 0.0000 as an answer, why?
And %f is replaced with %c it is printing B. I am not getting the reason.
Please explain !!
It is because your program invokes undefined behavior. You may get anything, either expected or unexpected.
C11: 7.29.2 Formatted wide character input/output functions:
If a conversion specification is invalid, the behavior is undefined.335) If any argument is not the correct type for the corresponding conversion specification, the behavior is
undefined.
printf("%f",a);
^ %f specifier expects arguments of type float/ double.
And %f is replaced with %c it is printing B. I am not getting the reason
ASCII code of character B is 66. Using %c specifier prints the (printable) character itself.
For printf():
[...] If any argument is not the type expected by the corresponding conversion specifier, or if there are less arguments than required by format, the behavior is undefined. If there are more arguments than required by format, the extraneous arguments are evaluated and ignored [...]
Although, for %c, you correctly get the expected 'B' (whose ASCII code is 66), it is not recommended (imaging when you pass in 666, which will get unexpected result as no ASCII code is 666). At least, you should do type-casting beforehand:
printf("%f", (float)a);
printf("%c", (char)a);
Again, remember always use the corresponding specifiers for different types.
If you use %f specifier and do not provide a float number, but int, the behaviour is undefined. In practice the memory starting in the location where your int is will be interpreted as float number, so what gets printed depends on internal representation of ints and floats.
For %c you got B since %c interprets your int as character code, and B's code is 66.
%f is used to print floating point number
%c is used to print character
%d is used to print integer number
so when you are using %c printf function converting from ascii value to character of B.
if you want to print the integer
printf("%d",a);
%c prints the character corresponding to 66 into ascii table.
By default %f will print 5 digits after the decimal point, but you can change the behaviour with %.3f (for 3 digits)

Why does scanf() need "%lf" for doubles, when printf() is okay with just "%f"?

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.

Resources