我想知道为什么输出为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我会得到
答案 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传递时,int
和float
的表示存在差异。在大多数ABI中,float
作为double
传递,因此它比int
长两倍(假设int
尺寸4和double
8)。因此,您可以尝试使用int64_t
数据类型。在这种情况下,如果您将某个浮点值的二进制表示拟合为整数,则可以看到不同的值。
答案 3 :(得分:0)
简而言之,我想知道
0.00000000
的任何值,输出值始终为i
的原因是什么?
简而言之,通过写作
printf("%f\n",i);
即使用int
打印%f
为undefined behaviour。输出可以是任何东西,甚至是你的电话号码或ATM密码。
引用标准,(你已经知道),从我这边强调
如果任何参数不是相应转换规范的正确类型,行为未定义。
答案 4 :(得分:0)
未定义的行为并不意味着您必须在不同的运行中获得不同的结果。它只意味着你不能指望任何明确定义的行为。
答案 5 :(得分:0)
printf
函数使用format specifiers
来计算弹出堆栈的内容。因此,当它看到%f时,将它们解释为double
。
在您的代码types are not compatible (as promoted according to the default argument promotions)
中,行为未定义。