printf(3)
's %f
format specifier wants a double
. Невозможно получить printf, чтобы принять float
, только double
или long double
.
акции аргумента по умолчанию C в указать, что звонки на VARIADIC функции, такие как foo(char *fmt, ...)
способствуют float
к double
и выполнять обычные целые акции целочисленных узких типов в int
, для задней арг, которые соответствуют ...
части прототипа. (То же самое относится ко всем аргументам для вызова функций без прототипа.) N1570 6.5.2.2 Function calls, subsections 6 and 7.
Таким образом, С не обеспечивает путь для вызывающего абонента, чтобы пропускать float
к printf
, так что это не имеет никакого преобразования для него, и %f
означает double
. (%lf
обычно также работает для double
, предполагая, что реализация игнорирует его для нецелых/wchar_t
конверсий). Обратите внимание, что scanf
отличается, потому что float *
и double *
не зависят от этих рекламных акций.
В этом случае нагрузки с CVTSS2SD .num, %xmm0
.
Если вы посмотрите на compiler output, вы увидите НКУ делать все, что вы сделали, и pxor
-нуль регистр первой разорвать ложную зависимость от старого значения %xmm0
. (плохой дизайн cvtss2sd оставляет верхние 64 бита адресата без изменений.) gcc errs на стороне предостережения и вставляет инструкции xor-zeroing, чтобы во многих случаях прерывать ложные зависимости.
Вы, вероятно, получить 0 поскольку верхние биты XMM0 случиться равным нулю. Таким образом, битовая диаграмма для 123.4f
в младших 32 битах мантиссы, когда printf
смотрит на низкие 64 бит xmm0 как double
(IEEE binary64 на x86).
Если вы попробуйте эквивалент с помощью float
(например, на http://www.h-schmidt.net/FloatConverter/IEEE754.html), установив несколько бит в нижней половине, вы получите очень маленькое денормальное число. Если вы использовали %g
(научная нотация) или %a
(hex), появятся ненулевые биты. (Если в MXCSR не включен режим Denormals Areero).
Удивительно для меня, что, несмотря на то, что я писал C++ много лет и многократно использовал printf ... Я никогда не знал этого. – cgmb
@cgmb: Да, это неочевидно. Я забыл, но даже не возможно передать 'float' функции var-args в C. Правила продвижения указывают на преобразование в' double'. Я ожидаю, что если это будет возможно, по крайней мере, у GNU C будет спецификатор формата. (Как '% hf' или что-то еще).Для меня я действительно только привязался к этому ограничению от просмотра asm, так как в противном случае компилятор всегда выполняет преобразование для вас. (Кроме того, из-за необходимости печатать 'float' с форматированием в формате'% a' в шестнадцатеричном стиле) –