简体   繁体   中英

Using printf to print float pointer using %d

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.

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:

  • Where to find the argument that was passed.
  • How to interpret the bits of that argument.

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•10 13 , − 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.
  • The pointers are cast to void * for printing. This ensures they are in a common form, suitable for %p , when passed.
  • I moved the \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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM