Why does printf print the incorrect value? - c

The following code always prints "0.00". I was expecting "7888". Should I convert it to double?
long l = 7888;
printf("%.2f", l);

%.2f is not a valid format for a long. You can cast it to double:
long l = 7888;
printf("%.2f", (double)l);
Here is a table (scroll a bit down) where you can see which codes are allowed for all number types.

%f expects a double and l variable is a long. printf() does not convert it's arguments to a type required by the format specifier all-by-itself magically.
FWIW, printf() being a variadic function, default argument promotion rule is applied on the supplied arguments, and it does not change a long to double, either. If at all, you want that conversion to happen, you have to cast the argument value explicitly.
You need to write something like
printf("%.2f", (double)l);
Please note, this code invokes undefined behaviour, without an explicit cast. Reference, C11, chapter §7.21.6.1, fprintf()
[....] If any argument is
not the correct type for the corresponding conversion specification, the behavior is undefined.

The %f format specifier expects a double, but you're passing it a long, so that's undefined behavior.
If you want to print it properly, you need to either use the %ld format specifier to print it as a long:
printf("%ld", l);
Or cast l to double to print it as a floating point number:
printf("%.2f", (double)l);

I was expecting "7888".
This happens because you are trying to print LONG with FLOAT identifier.
The compiler complains about that if you turn your setting on:
program.c:5:5: error: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘long int’ [-Werror=format=]
printf("%f", l);
^
cc1: all warnings being treated as errors
.
Should I convert it to double?
By the way you can cast it too, if this is what you really need.
I think this is what you realy need:
#include<stdio.h>
int main(void){
long l = 7888;
printf("%ld", l);
return 0;
}
7888

You cannot printf a long proberly with a float identifier. What do you want do achieve?

Related

Can't make printf happy. Rejecting format strings of "i" and "l" [duplicate]

This question already has answers here:
What is the conversion specifier for printf that formats a long?
(7 answers)
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long int’ [-Wformat=]
(3 answers)
Closed 1 year ago.
long int triagedOut = 0;
printf("%i", triagedOut);
main.c|89|warning: format '%i' expects argument of type 'int', but
argument 2 has type 'long int' [-Wformat=]|
I actually get that message twice for the same line. ???
OK, so I will change it to the long int specifier "l" and, then...
printf("%l", triagedOut);
main.c|89|warning: conversion lacks type at end of format [-Wformat=]|
main.c|89|warning: too many arguments for format
[-Wformat-extra-args]|
And I get these two messages twice, too.
I don't even know how there could be too many of anything. Just 1 of everything. What's it trying to tell me?
You need to use %ld for long int.
printf("%ld", triagedOut);
Note also these remarks:
Format %i indeed expects an int argument, and you are passing a long int, which is a different type and may have a different size, depending on the target platform.
Format %l is incomplete: l is just a length modifier, you also need a conversion specifier such as i, d, u, x... hence the proposed correction %ld. i and d are equivalent for printf(), but they have a different meaning for scanf(): %i converts an integer expressed in decimal, octal or hexadecimal as determined by its initial characters, whereas %d only converts an integer expressed in decimal.
int i;
sscanf("0x10", "%i", &i); // sets i to 16
sscanf("0x10", "%d", &i); // sets i to 0
sscanf("010", "%d", &i); // sets i to 10
sscanf("010", "%i", &i); // sets i to 8
The reason you get the messages twice might be that these are warning messages, not preventing the compilation from proceeding, and your IDE might compile 2 different versions of the executable, one in debug mode and one in production mode.
I think you should use %ld or %li instead of %l or %i for printing long integer.
long int triagedOut = 0;
printf("%li", triagedOut);

Variable of type double not working when read by scanf()

#include <stdio.h>
int main(){
double d;
scanf("%f", &d);
printf("%f\n\n", d);
system("pause");
return 0;
}
This is what I get:
error.
This code is meant to read the variable double and display it on the screen but it does only display "0.0...".
If I just change the variable type to float it does exactly what I want but if I make it a double it just reads '0'. Why?
In your code,
scanf("%f", &d);
is wrong. For scanf(), %f expects a pointer to float as argument.
Quoting C11, chapter §7.21.6.2, fscanf()
a,e,f,g
Matches an optionally signed floating-point number, infinity, or NaN, whose
format is the same as expected for the subject sequence of the strtod
function. The corresponding argument shall be a pointer to floating.
In case you want to scan a double, you have to use
scanf("%lf", &d);
FWIW, passing incompatible type of argument for any format specifier invokes undefined behavior.
Quoting C11,
[...] Unless assignment suppression was indicated by a *, the
result of the conversion is placed in the object pointed to by the first argument following
the format argument that has not already received a conversion result. If this object
does not have an appropriate type, or if the result of the conversion cannot be represented
in the object, the behavior is undefined.

C 's format specifier

I have this code in C-
#include <stdio.h>
void main(void)
{
int a=90;
float b=4;
printf("%f",90%4);
}
It gives an output 0.0000,I am unable to understand why???
i know that 90%4 returns 2 and the format specifier specified is %f,which is for double,but what I expect is-
That it will give an error,but it is showing 0.0000 as output.
Can someone please explain why?
The type of 90%4 will be int.
The behaviour on using %f as the format specifier for an int is undefined.
The output could be 2, it could be 0. The compiler could even eat your cat.
This discrepancy comes about because the compiler and library do not communicate regarding types. What happens is that your C compiler observes that printf is a variadic function taking any number of arguments, so the extra arguments get passed per their individual types. If you're lucky, it also parses the format string and warns you that the type doesn't match:
$ gcc -Wformat -o fmterr fmterr.c
fmterr.c: In function ‘main’:
fmterr.c:6:2: warning: format ‘%f’ expects argument of type ‘double’,
but argument 2 has type ‘int’ [-Wformat=]
printf("%f",90%4);
^
But this is still just a warning; you might have replaced printf with a function with different behaviour, as far as the compiler is concerned. At run time, floating point and integer arguments may not even be placed in the same place, and certainly don't have the same format, so the particular result of 0.0 is not guaranteed. What really happens may be related to the platform ABI. You can get specified behaviour by changing the printf argument to something like (float)(90%4).
printf is a variadic function. Such functions are obscure, with no type safety worth mentioning. What such functions do is to implicitly promote small integer types to type int and float to double, but that is it. It is not able to do more subtle things like integer to float conversion.
So printf in itself can't tell what you passed on it, it relies on the programmer to specify the correct type. Integer literals such as 90 are of type int. With the %f specifier you told printf that you passed a double, but actually passed an int, so you invoke undefined behavior. Meaning that anything can happen: incorrect prints, correct prints, program crash etc.
An explicit cast (double)(90%4) will solve the problem.
%f expects a double and you pass int(90%4=2) in printf. Thus ,leading to Undefined Behaiour and can give output anything .
You need to explicitly cast -
printf("%f",(double)(90%4));
Don't try this as compiler will generate an error (as pointed by #chux Sir )-
printf("%f",90%(double)4);
In short: there is no error checking for format specifiers. If your format is looking for a double, then whatever you pass as an argument (or even if you pass nothing) will be interpreted as a double.
By default, 90%4 gives an integer.
If you print integer with %f specifier, it will print 0.
For example, printf("%f", 2); will print 0.
You typecast result with float, you will get 2.00000.
printf("%f",(float) (90%4)); will print 2.00000
Hope it clarifies.

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

Scanf/Printf double variable C

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'.

Resources