Printf for float behaves differently if position is changed

I have below code snippet:

float i=85.00; printf("%f %p",i,i); 

which prints o / p:

 85.00000 (nil) 

But when I change the order as shown below:

  float i=85.00; printf("%p %f",i,i); 

o / p:

 (nil) 0.00000 

While I expect that a similar o / p should be printed as before, in that order. What is the behavior anyone can explain?

+4
source share
3 answers

What you do is undefined behavior. The format specifier is %p promises, which you pass to the pointer (in particular, the void* pointer), and instead you pass double ( float ) to get the double value when passing to variational functions like printf ). Thus, as soon as you do not satisfy the requirement, the compiler and implementation will be free to do whatever they want, and listing 0 instead of 85 in the second case is completely legal.

What can happen is that the compiler uses a calling convention that puts floating-point values โ€‹โ€‹in separate registers (for example, the x87 floating-point stack or SIME SSE2 registers) instead of the stack, while integer values โ€‹โ€‹like pointers are passed to stack. Therefore, when the implementation sees the %p format specifier, it tries to read the argument from the stack, when in fact the argument is actually in a different place.

As already mentioned, you really have to compile with the -Wall option (assuming GCC or a GCC compatible compiler). This will help you catch such errors.

+8
source

printf() expects a pointer to the %p format specifier, while you are passing a float value. This behavior is undefined.

If you want to print the address, then pass the address:

 printf("%f %p",i, &i); 

If you enable warnings , you will see a problem:

warning: format '% p expects an argument of type void *, but argument 3 is of type' double [-Wformat]

+8
source

You will probably encounter something undefined behavior ; printing a float as a pointer makes no sense.

And GCC 4.8, called as gcc -Wall , warns you correctly:

 dwakar.c:5:3: warning: format '%p' expects argument of type 'void *', but argument 3 has type 'double' [-Wformat=] printf("%f %p",i,i); ^ 

Therefore, please use gcc -Wall to compile your code and fix it until warnings are given.

Note that at the ABI level, floating point and pointer arguments are passed through different registers. Thus, the implementation probably prints as the pointer (uninitialized or old) the contents of any register.

+3
source

Source: https://habr.com/ru/post/1487997/


All Articles