printf(3)
's %f
format specifier wants a double
. Non è possibile ottenere che printf accetti uno float
, solo double
o long double
.
promozioni argomento default di C specificano che le chiamate a funzioni come variadic foo(char *fmt, ...)
promuovono float
a double
, ed eseguono le solite promozioni interi di tipi interi strette per int
, per trailing args che corrispondono alla parte ...
del prototipo. (Lo stesso vale per tutti gli argomenti per la chiamata di funzioni senza alcun prototipo.) N1570 6.5.2.2 Function calls, subsections 6 and 7.
Così C fornisce alcun modo per un chiamante passare un float
a printf
, quindi ha alcuna conversione per esso, e %f
significa double
. (%lf
di solito funziona anche per double
, supponendo che l'implementazione lo ignori per le conversioni non interi/wchar_t
). Si noti che scanf
è diverso, perché float *
e double *
non sono interessati da tali promozioni.
In questo caso, carico con CVTSS2SD .num, %xmm0
.
Se si guarda alla compiler output, vedrete gcc fare quello che hai fatto, e pxor
-Zero registro primo a rompere la falsa dipendenza il vecchio valore di %xmm0
. (Il design scarso di cvtss2sd lascia invariati i 64 bit superiori della destinazione.) gcc eroga sul lato della cautela e inserisce istruzioni xor-zero per rompere le false dipendenze in molti casi.
Probabilmente stai ricevendo 0 perché i bit superiori di xmm0 capita di essere pari a zero. Quindi il pattern di bit per 123.4f
nei 32 bit bassi della mantissa, quando printf
esamina i 64 bit bassi di xmm0 come double
(IEEE binary64 su x86).
Se si prova l'equivalente con un float
, (ad esempio su http://www.h-schmidt.net/FloatConverter/IEEE754.html), l'impostazione di alcuni bit nella metà bassa, si ottiene un numero denormal molto piccolo. Se hai usato %g
(notazione scientifica) o %a
(hex), i bit diversi da zero verrebbero visualizzati. (A meno che tu non abbia abilitato la modalità Denormals Zero in MXCSR.)
fonte
2016-05-07 01:20:42
È incredibile per me che, nonostante abbia scritto C++ per anni e usando la stampa molte, molte volte ... non lo sapevo mai. – cgmb
@cgmb: sì, non è ovvio. Dimentico, ma potrebbe anche non essere possibile passare un 'float' a una funzione var-args in C. Le regole di promozione specificano la conversione in' double'. Mi aspetto che se fosse possibile, almeno GNU C avrebbe un identificatore di formato per questo. (Come '% hf' o qualcosa del genere).Per quanto mi riguarda, mi sono davvero limitato a questa limitazione osservando asm, poiché altrimenti il compilatore fa sempre la conversione per te. (Inoltre, in realtà dal voler stampare un 'float' con'% a' formattazione in stile hex) –