Используйте
printf("%f\n",(float)i);
Компилятор автоматически не переводит ваше int в float
Изменить: я думаю, что это интересный вопрос, поэтому я нашел похожую статью: Код функции printf на C
Затем я попытался изучить __printf , vfprintf и ___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;
}
В vfprintf определяется таблица jump_table, которая обрабатывает определенный формат (%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
};
Затем они помещают LABEL в эту функцию vfprintf (что-то вроде случая переключения)
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):
...
}
В Label form_float они определяют структуру, определяющую формат 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)
для печати вывода.
Вывод: если входной формат неверный, у нас будет неверный формат struct info
, то и вывод тоже должен быть неверным.
person
Ngo Thanh Nhan
schedule
09.07.2015
%f
ожидает значение с плавающей запятой в регистре с плавающей запятой, а поскольку его нет, отображается0.0000
. (Результатом попытки чтения из неинициализированного регистра с плавающей запятой также является Undefined Behavior.) - person Jongware   schedule 09.07.2015"%e"
вместо"%f"
. Это даст больше понимания. Около половины всехdouble
печатают 0,000000, так как это значение очень мало. При использовании"%e"
подозрительные изменения наi
проявятся сами собой. - person chux - Reinstate Monica   schedule 09.07.2015i
интерпретируется как 64-битное двойное число, и, учитывая распространенные представления с плавающей запятой, будет соответствовать чему-то в окрестности2^-47
, то есть от 0 до что-то вроде 13 или 14 знаков после запятой (при условии, что вы используете x86). - person John Bode   schedule 09.07.2015int
(вероятно, 32-битный), аprintf()
ищетdouble
(вероятно, 64-битный). Скорее всего не совпадают размеры. Учитывая вывод"6.952880e-308"
, который может иметь шестнадцатеричный шаблон0028FF8FE2FFCBFD
и совсем не похож наi = 0x0000000A
, я подозреваю, что несоответствие в способе передачи данных также способствовало необычному результату. Чтобы узнать, вы можете начать сбрасывать ассемблерный код и анализировать его, чтобы определить, какое неопределенное поведение произошло, но это работа и сомнительная ценность. - person chux - Reinstate Monica   schedule 09.07.2015