printf(3)
's %f
format specifier wants a double
. Es gibt keine Möglichkeit, printf dazu zu bringen, eine float
, nur double
oder long double
zu akzeptieren.
der C Standardargument aktionen angeben, die Funktionen wie foo(char *fmt, ...)
fördern float
zu double
, und führen Sie die üblichen ganzzahligen aktionen von schmalen Integer-Typen zu int
, für Hinter args variadische aufruft, die den ...
Teil des Prototyps entsprechen. (Gleiches gilt für alle Argumente zum Aufruf von Funktionen ohne Prototyp.) N1570 6.5.2.2 Function calls, subsections 6 and 7.
Somit bietet C keine Möglichkeit für einen Anrufer eine passieren float
printf
zu, so hat es keine Umwandlung für sie, und %f
double
bedeutet. (%lf
funktioniert normalerweise auch für double
, vorausgesetzt, die Implementierung ignoriert es für nicht ganzzahlige/wchar_t
Konvertierungen). Beachten Sie, dass sich scanf
davon unterscheidet, da float *
und double *
nicht von diesen Werbeaktionen betroffen sind.
In diesem Fall Last mit CVTSS2SD .num, %xmm0
.
Wenn Sie bei compiler output anschauen, werden Sie sehen gcc alles tun, du hast, und pxor
-Nullsignal das Register zuerst die falsche Abhängigkeit von dem alten Wert von %xmm0
zu brechen. (Das schlechte Design von cvtss2sd lässt die oberen 64 Bits des Ziels unverändert.) gcc irrt auf der Seite der Vorsicht und fügt xor-Nullsetzungsbefehle ein, um in vielen Fällen falsche Abhängigkeiten zu brechen.
Du bist wahrscheinlich immer 0, weil die oberen Bits xmm0 Null sein passieren. Also das Bitmuster für 123.4f
in den niedrigen 32 Bits der Mantisse, wenn printf
die niedrigen 64 Bits von xmm0 als double
betrachtet (IEEE binary64 auf x86).
Wenn Sie das Äquivalent mit einem float
versuchen (z. B. unter http://www.h-schmidt.net/FloatConverter/IEEE754.html), setzen Sie einige Bits in der unteren Hälfte, und Sie erhalten eine sehr kleine Denormalzahl. Wenn Sie %g
(wissenschaftliche Notation) oder %a
(Hex) verwendet haben, würden die Nicht-Null-Bits angezeigt. (Es sei denn, Sie hatten Denormals Are Zero-Modus in der MXCSR aktiviert.)
Es ist erstaunlich für mich, dass, obwohl C++ seit Jahren geschrieben und printf viele, viele Male verwendet ... Ich wusste das nie. – cgmb
@cgmb: Ja, es ist nicht offensichtlich. Ich vergesse, aber es ist vielleicht nicht einmal möglich, ein "float" an eine var-args-Funktion in C zu übergeben. Die Promotionsregeln spezifizieren die Umwandlung in "double". Ich denke, wenn es möglich wäre, hätte zumindest GNU C einen Formatbezeichner dafür. (Wie '% hf' oder etwas).Für mich hat ich diese Einschränkung nur von asm aus betrachtet, da sonst der Compiler immer die Konvertierung für Sie übernimmt. (Auch von eigentlich aus wollen einen 'float' mit'% a' hex-style Formatierung drucken) –