Как отмечалось в других ответах, это происходит из-за несоответствия между строкой формата и типом аргумента.
Я предполагаю, что вы используете x86 здесь (на основе наблюдаемых результатов).
Аргументы передаются в стек, а x/y
, хотя и имеет тип float
, будет передан как double
в функцию varargs (из-за правил типа «повышение»).
int
- это 32-разрядное значение, а double
- это 64-разрядное значение.
В обоих случаях вы передаете x/y
(= 0,5) дважды.Представление этого значения в виде 64-битного double
равно 0x3fe0000000000000
.Как пара 32-битных слов, она сохраняется как 0x00000000
(младшие 32-битные), за которыми следует 0x3fe00000
(старшие 32-битные).Таким образом, аргументы в стеке, как видно из printf()
, выглядят так:
0x3fe00000
0x00000000
0x3fe00000
0x00000000 <-- stack pointer
В первом из ваших двух случаев %d
вызывает первое 32-битное значение, 0x00000000
, чтобы выскочить и распечатать.%f
выводит следующие два 32-битных значения: 0x3fe00000
(младшие 32-битные 64-битные double
), затем следует 0x00000000
(наиболее значимое).Результирующее 64-битное значение 0x000000003fe00000
, интерпретируемое как double
, является очень небольшим числом.(Если вы измените %f
в строке формата на %g
, вы увидите, что это почти 0, но не совсем).
Во втором случае %f
правильно выводит первое double
, и %d
выдает 0x00000000
половину второй double
, так что, похоже, работает.