Von einer früheren Frage :
Wenn Sie versuchen, ein
float
anprintf
zu übergeben, wird es zudouble
hochgestuft. bevorprintf
es empfängt
printf()
ist eine variadische Funktion oder? Also fördert eine variadic Funktion ein float
Argument zu einem double
, bevor es übergeben wird?
Ja, Float-Argumente für variadic-Funktionen werden zu double hochgestuft.
Der Entwurf C99 Standard Abschnitt 6.5.2.2
Funktionsaufrufe sagt :
[...] und Argumente, die have type float wird zu double hochgestuft. Diese werden als Standardargument bezeichnet Werbeaktionen [...]
aus dem Entwurf des C ++ - Standards Abschnitt 5.2.2
Funktionsaufruf:
[...] ein Fließkommatyp, der dem Fließkomma unterliegt promotion (4.6) wird der Wert des Arguments in Typ vor dem Aufruf. [...]
und Abschnitt 4.6
:
Ein Prvalue vom Typ float kann in einen prvalue vom Typ double konvertiert werden. Der Wert ist unverändert
cppreference deckt die Standardkonvertierungen für variadic Funktion in C ++ gut:
- std :: nullptr_t wird in void *
konvertiert- float-Argumente werden in double wie in Floating-Point-Promotion konvertiert
- bool-, char-, short- und unscoped-Enumerationen werden wie in ganzzahlige Heraufstufungen
in int-Typen oder breitere Integer-Typen konvertiert
Wir können in C und vermutlich in C ++ sehen, dass diese Konvertierung für die Kompatibilität mit K & amp; RC von Begründung für internationale Standard-Programmiersprachen-C ( Hervorhebung von mir ):
Aus Gründen der Kompatibilität mit der bisherigen Vorgehensweise werden alle Argumentaktionen wie folgt durchgeführt in K & amp; R in Ermangelung einer Prototyp-Deklaration beschrieben, einschließlich die nicht immer wünschenswerte Promotion von float zu verdoppeln.
Was den warum Teil der Frage anbelangt, ist es einfach: Die C (und C ++) Standards betrachten double
als den "Standard" Gleitkommatyp. Nicht float
(was bei vielen von uns Programmierern standardmäßig bei der Verwendung von Gleitkommazahlen ist).
Dies kann durch Beobachtung gesehen werden:
3.14
ist ein double
(wenn du ein float
willst, musst du einen zusätzlichen Schritt machen und ein f
anhängen) double
(zB sin()
benötigt double
; wenn Sie float
wollen, müssen Sie sinf()
verwenden) Damit erscheint es "natürlicher", dass ein float
in einem variadischen Funktionsaufruf zu double
hochgestuft wird, da double
der "natürliche" Standard in der Sprache ist.
Gegeben sei ein Funktionsprototyp, der Typ float wird nur dann automatisch befördert, wenn er in ablaufenden Argumenten verwendet wird. Funktionsdruck verwendet diese:
%Vor% 1 (Zitiert nach: ISO / IEC 9899: 201x 6.5.2.2 Funktionsaufrufe)
6. Die Integer-Promotions werden für jedes Argument ausgeführt, und Argumente, die
have type float wird zu double hochgestuft. Diese werden als Standardargument bezeichnet
Werbeaktionen.
7. Das Standardargument
Aktionen werden für nachfolgende Argumente ausgeführt.
Weil der Standard (C99 oder C11 ) dies sagt. Siehe answer by 2501 .
Dafür gibt es mehrere pragmatische Gründe: Geschichte (die ersten Implementierungen von C wurden für die Systemprogrammierung verwendet, wobei Fließkommaoperationen keine Rolle spielen), und die Tatsache, dass es aktuell ist (Tablet, Desktop, Server ...) Prozessoren, arithmetische Operationen auf double
sind ungefähr so effizient wie float
(aber einige billige Mikrocontroller haben keine FPU oder können nur float
per Hardware hinzufügen und benötigen eine Bibliothek für jede Operation auf double
) . Ich denke, dass eine solche Regel endlich einfachere Aufrufkonventionen und ABI s.
Denken Sie an float
als eine Art short double
(was natürlich illegal in C ist). A float
ist vor allem nützlich, wenn Sie Speicher komprimieren müssen (und den Verlust der Genauigkeit leisten können). Siehe auch Ссылка für mehr.
Tags und Links c c++ variadic-functions printf