Reputation: 39
Can Anyone tell me why this happens ..... I compiled and executed it with the latest GCC compiler.
Please don't give suggestions like "place %f in place of %d" and etc..
#include <stdio.h>
int main(void)
{
printf("%d" , 3.0 / 2.0);
return 0;
}
Expected Output : 1
Gives Output : 0
#include <stdio.h>
int main(void)
{
printf("%f" , 3 / 2);
return 0;
}
Expected Output : 1.000000
Gives Output : 0.000000
Upvotes: 3
Views: 70
Reputation: 224596
Computing platforms—sets of hardware and software working together—define how arguments should be passed to functions. This specification of how arguments are passed is part of a specification typically called the application binary interface (ABI).
The details about how an argument should be passed may depend on several factors, including:
The means by which an argument should be passed may include:
The expression 3 / 2
has an int
type. It will be passed in the way the ABI specifies for an int
argument. When you specify %f
in a printf
format, printf
expects a double
, and printf
looks for the argument in the place the ABI specifies for a double
.
Thus, in printf("%f" , 3 / 2);
, there is no guarantee that printf
even sees the int
value that was passed. It may get data from the wrong memory or register entirely.
If printf
does get the data for the int
value, it will interpret those bytes as if they were double
value. The values of bytes have different meanings when they are encoding an int
than when they are encoding a double
. So the values in the bytes that encode an int
value of 1 do not encode a 1 when they are encoding a double
value. So, even if printf
, when it is formatting a double
for %f
, gets the bytes for the int
value of 1, the characters it produces are not likely to be “1”.
The C standard defines how you should use printf
and its format specifiers so that the ABI can work. When you violate the C rules about matching argument types with format specifiers, the C standard does not define what behavior results. It leaves you at the mercy of the C implementation. Historically, this meant you were violating the ABI, and the program would break for the reasons I describe above. Over time, compilers have become more aggressive about optimization and other program transformations, with the result that violating the rules of the C standard can transform program behavior in more surprising ways.
Upvotes: 1
Reputation: 225827
In the first case, you pass an expression of type double
when the format specifier expects an int
, and in the second case you pass an expression of type int
when the format specifier expects a double
.
Using the wrong format specifier invokes undefined behavior as dictated by the C standard, meaning you can't reliably predict how your program will behave. Different compilers may manifest undefined behavior in different ways, as well as different optimizations settings on the same compiler.
Attempting to reason away undefined behavior serves no purpose. Just make sure your program is well behaved, which in this case means using the correct format specifier.
That being said, compilers for x86 systems typically pass floating point parameters in floating point registers while integers are passed on the stack. So when printf
tries to read a parameter of a given type it ends up reading whatever garbage happened to be where it was looking because the actual parameter isn't there at all.
Upvotes: 1