printing int using %f format specifier [duplicate]

不羁岁月 提交于 2019-12-13 09:39:59

问题


I wanted to know why output is coming as 0.000000. I know printing int using float format specifier or using a type of value using b type gives unspecified behaviour as written in many place. I'm quoting it

"If a conversion specification is invalid, the behaviour is undefined. If any argument is not the correct type for the corresponding conversion specification, the behaviour is undefined."

But it is always giving 0.000000 there must be something defined going either in register or in assembly code.

In short I wanted to know what cause output to be always 0.000000 for any value of i?

#include<stdio.h>
int main()
{
    int i=10;
    printf("%f\n",i);
    return 0;
}

All said I know value of i may be somewhere in output but due to precession window size it is not shown on console. If I use %e I'm getting


回答1:


You may get same results for a day and another result on next day, that is the all story about undefined behavior. Standard don't guarantee any deterministic result for undefined behavior.

You should use proper type specifiers while printing using printf




回答2:


Use
printf("%f\n",(float)i);

The compiler do not automatically cast your int to float

Edit: I think this is an interesting question, so I found a similar article: Code for printf function in C

Then I tried to explore __printf , vfprintf and ___printf_fp

__printf (const char *format, ...)
{
   va_list arg;
   int done;

   va_start (arg, format);
   done = vfprintf (stdout, format, arg);
   va_end (arg);

   return done;
}

In vfprintf, they define a jump_table, that processes the specific format (%d, %f, %x ...)

static const uint8_t jump_table[] =
 {
   /* ' ' */  1,            0,            0, /* '#' */  4,
              0, /* '%' */ 14,            0, /* '\''*/  6,
              0,            0, /* '*' */  7, /* '+' */  2,
              0, /* '-' */  3, /* '.' */  9,            0,
   /* '0' */  5, /* '1' */  8, /* '2' */  8, /* '3' */  8,
   /* '4' */  8, /* '5' */  8, /* '6' */  8, /* '7' */  8,
   /* '8' */  8, /* '9' */  8,            0,            0,
              0,            0,            0,            0,
              0, /* 'A' */ 26,            0, /* 'C' */ 25,
              0, /* 'E' */ 19, /* F */   19, /* 'G' */ 19,
              0, /* 'I' */ 29,            0,            0,
   /* 'L' */ 12,            0,            0,            0,
              0,            0,            0, /* 'S' */ 21,
              0,            0,            0,            0,
   /* 'X' */ 18,            0, /* 'Z' */ 13,            0,
              0,            0,            0,            0,
              0, /* 'a' */ 26,            0, /* 'c' */ 20,
   /* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19,
   /* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28,            0,
   /* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,
   /* 'p' */ 22, /* 'q' */ 12,            0, /* 's' */ 21,
   /* 't' */ 27, /* 'u' */ 16,            0,            0,
   /* 'x' */ 18,            0, /* 'z' */ 13
 };

Then they put LABEL in this vfprintf function (something like switch case)

int vfprintf (FILE *s, const CHAR_T *format, va_list ap)
{
...
LABEL (form_percent):           
  /* Write a literal "%".  */   
  outchar (L_('%'));            
  break;                        

LABEL (form_integer):           
  /* Signed decimal integer.  */
  base = 10;

LABEL (form_float): 
...
}

In Label form_float, they define a struct which defined float format

struct printf_info info = { 
.prec = prec,                    
.width = width,                  
.spec = spec,                    
.is_long_double = is_long_double,
.is_short = is_short,            
.is_long = is_long,              
.alt = alt,                      
.space = space,                  
.left = left,                    
.showsign = showsign,            
.group = group,                  
.pad = pad,                      
.extra = 0,                      
.i18n = use_outdigits,           
.wide = sizeof (CHAR_T) != 1 
}; 

Finally, they call

int ___printf_fp (FILE *fp, 
                  const struct printf_info *info,
                  const void *const *args)

to print the output.

Conclusion: if input format is not correct, we wil have a wrong format struct info, then output must be wrong too.




回答3:


Undefined behaviour doesn't mean that you have to obtain different results in different runs. It only means that you must not expect any well-defined behaviour.




回答4:


You are pushing integer into stack, but telling printf that it is floating point.

Here is a correct example:

#include<stdio.h>
int main()
{
  int i=10;
  printf("%f\n", (float)i);
  return 0;
}

Addition:

There is a difference of representation of int and float when passing as varargs. In most ABIs, float is passed as double, so it is twice as long than int (assuming int size 4 and double 8). So you can experiment with int64_t data type instead. In this case, you can see different values if you fit binary presentation of some floating point value into integer.




回答5:


In short I wanted to know what cause output tu be always 0.00000000 for any value of i?

In short, by writing

  printf("%f\n",i);

i.e., printing an int using %f is undefined behaviour. Output can be anything, even your phone number or ATM PIN, also.

To quote the standard, (which you already know), with emphasis from my side

If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.




回答6:


The printf function uses the format specifiers to figure out what to pop off the stack. So when it sees %f, interprets them as double.

As here in your code types are not compatible (as promoted according to the default argument promotions) behaviour is undefined.



来源:https://stackoverflow.com/questions/31319739/printing-int-using-f-format-specifier

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!