问题
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:
Useprintf("%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 ofi
?
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