Как уже говорили другие, вы должны использовать формат %f
для печати чисел, а не %d
, который предназначен для целых чисел. Существует также %e
, который печатает поплавок в научной нотации вместо фиксированной, а также %g
, который печатает его в научной или фиксированной форме, в зависимости от того, что короче.
Причина, по которой он печатается как 0, заключается в том, что аргументы с плавающей запятой автоматически преобразуются в удвоенные значения при передаче в качестве аргументов в функции с переменными числами (то есть функции, которые принимают неопределенное количество аргументов), такие как printf()
. Представления чисел 2 и 3 (значения x
и y
) в виде двойных чисел равны 0x4000000000000000 и 0x4008000000000000 соответственно, как рассчитано калькулятором IEEE-754 преобразования с плавающей точкой .
На машинах с прямым порядком байтов (например, на базе x86) модификатор %d
извлекает следующие 4 байта из стека и интерпретирует их как целое число. Таким образом, когда вы передаете число с плавающей точкой 2, оно конвертируется в двойное число как 0x4000000000000000, что в порядке с прямым порядком байтов равно 00 00 00 00 00 00 00 40. Первые четыре байта составляют целое число 0, так что это то, что распечатывается.
Обратите внимание, что если вы напечатаете оба числа в одном выражении вместо двух, вы получите более удивительный результат:
printf("x=%d y=%d\n", x, y);
// Output: x=0 y=1073741824
Большинство компиляторов могут предупреждать вас об этих типах ошибок, если вы установите достаточно высокий уровень предупреждения. С GCC вы должны скомпилировать с опцией -Wformat
(или -Wall
, которая включает в себя -Wformat
), и она предупредит вас, когда вы попытаетесь напечатать плавающее число с %d
случайно.