使用%f格式说明符打印int

时间:2015-07-09 13:58:38

标签: c casting floating-point printf format-specifiers

我想知道为什么输出为0.000000。 我知道使用float格式说明符打印int或使用b类型使用某种类型的值给出了许多地方所写的未指定的行为。 我在引用它

  

“如果转换规范无效,则行为为   未定义。如果任何参数不是正确的类型   相应的转换规范,行为未定义。“

但它始终给出0.000000,必须在寄存器或汇编代码中定义一些东西。

简而言之,我想知道对于i的任何值,输出总是0.000000的原因是什么?

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

所有人都知道我知道i的价值可能在输出的某个地方,但由于进动窗口大小,它不会显示在控制台上。 如果我使用%e我会得到 enter image description here

6 个答案:

答案 0 :(得分:1)

您可能会在一天内获得相同的结果,并在第二天获得另一个结果,这是关于 undefined behavior 的全部故事。标准不保证未定义行为的任​​何确定性结果。

使用printf

进行打印时,应使用正确的类型说明符

答案 1 :(得分:1)

使用
Contains

编译器不会自动将int转换为float

修改: 我认为这是一个有趣的问题,所以我发现了一篇类似的文章: Code for printf function in C

然后我尝试探索__printf,vfprintf和___ printf_fp

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

在vfprintf中,他们定义了一个jump_table,用于处理特定格式(%d,%f,%x ...)

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

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

   return done;
}

然后他们将LABEL放在这个vfprintf函数中(类似于switch case)

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
 };

在Label form_float 中,它们定义了一个定义浮点格式的结构

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): 
...
}

最后,他们打电话给

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 
}; 

打印输出。

结论:如果输入格式不正确,我们的格式int ___printf_fp (FILE *fp, const struct printf_info *info, const void *const *args) 会有错误,那么输出也一定是错的。

答案 2 :(得分:0)

您正在将整数推入堆栈,但告诉printf它是浮点数。

这是一个正确的例子:

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

增加:

作为varargs传递时,intfloat的表示存在差异。在大多数ABI中,float作为double传递,因此它比int长两倍(假设int尺寸4和double 8)。因此,您可以尝试使用int64_t数据类型。在这种情况下,如果您将某个浮点值的二进制表示拟合为整数,则可以看到不同的值。

答案 3 :(得分:0)

  

简而言之,我想知道0.00000000的任何值,输出值始终为i的原因是什么?

简而言之,通过写作

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

即使用int打印%fundefined behaviour。输出可以是任何东西,甚至是你的电话号码或ATM密码。

引用标准,(你已经知道),从我这边强调

  

如果任何参数不是相应转换规范的正确类型,行为未定义。

答案 4 :(得分:0)

未定义的行为并不意味着您必须在不同的运行中获得不同的结果。它只意味着你不能指望任何明确定义的行为

答案 5 :(得分:0)

printf函数使用format specifiers来计算弹出堆栈的内容。因此,当它看到%f时,将它们解释为double

在您的代码types are not compatible (as promoted according to the default argument promotions)中,行为未定义。