Reputation: 35
When i run this code it prints address of a in 1st printf, and value of a in 2nd printf.
#include <stdio.h>
int main()
{
float a=7.999999;
float *b,*c;
b=&a;
c=b;
printf ( "\n%u %u %u", &a, b, c );
printf ("\n%f %f %f %f",a,*( &a ),*b,*c );
}
But When i change %f to %d in 2nd printf like this.
#include <stdio.h>
int main()
{
float a=7.999999;
float *b,*c;
b=&a;
c=b;
printf ( "\n%u %u %u", &a, b, c );
printf ("\n%d %d %d %d",a,*( &a ),*b,*c );
}
it prints random values in 2nd printf please explain why. float pointer should be printed using %f but why can't by using %d.
Upvotes: 2
Views: 2976
Reputation: 12708
%d
REQUIRES that the argument is an int
value. (and this is the reason you are getting garbage)
If you want to print your floats as integers, use %0.0f
instead. This will print the value rounded to the nearest integer, and with no decimals (I'm not sure now if this prints the decimal dot or not, but if it does, try the alternative %0.0g
)
Upvotes: 1
Reputation: 223842
why float pointer should be printed using %f but why can't by using %d.
The conversion specification (%d
or %f
) tells printf
two things:
On the first point, modern processors commonly have different registers for integer data and floating-point data. Due to this and related reasons, the rules for how arguments are passed to subroutines (part of the Application Binary Interface for a computing environment) typically say that the first few integer arguments are passed in certain integer registers and the first few floating-point arguments are passed in floating-point registers. (After the first few arguments, additional arguments are typically passed on the hardware stack.)
So, when you tell printf
to convert a number with %d
but pass it a floating-point argument, printf
may take the value from some integer register, but the floating-point argument is not there. It is in some floating-point register. And then printf
prints the wrong value.
On the second point, the values of integers and floating-point numbers are encoded in bits differently. %d
tells printf
to interpret the bits as a binary number (along with some scheme for representing negative numbers, most frequently two’s complement). %f
tells printf
to interpret the bits as a number encoding with a floating-point format. Also, due to C history, float
arguments to printf
are passed as double
. The most common floating-point format for double
uses one bit for the sign, 11 bits for an exponent of two, and 52 bits for a significand portion. (In ordinary scientific notation, for the numeral −3.74•1013, − is the sign, 13 is the exponent, and 3.74 is the significand.) If printf
did take some or all of the bits that encoded a double
and interpreted them according to %d
, it would print a number very different from the value of the floating-point number (except by exceedingly rare coincidence).
Also note that no pointers are printed or passed in printf ("\n%d %d %d %d",a,*( &a ),*b,*c );
. a
, *( &a )
, *b
, and *c
are all a
.
In printf ( "\n%u %u %u", &a, b, c );
, the pointers are printed incorrectly. Correct code is printf("%p %p %p\n", (void *) &a, (void *) b, (void *) c);
. Here I have made three changes:
%p
is a correct conversion specification for printing pointers. Sometimes printing with %u
will print the same value (although in decimal rather than hexadecimal), but, if that happens, it is just because pointers get passed in the same places as unsigned int
, they are the same size, and the errors did not fall afoul of compiler optimization.void *
for printing. This ensures they are in a common form, suitable for %p
, when passed.\n
to the end of the string instead of the beginning. C is designed for new-line characters to be at the ends of the lines instead of the starts, because, when there is a new-line character, it sends output to interactive devices immediately instead of holding it in a buffer.Upvotes: 6