Why does printf() promote a float to a double?
Solution 1:
Yes, float arguments to variadic function are promoted to double.
The draft C99 standard section 6.5.2.2
Function calls says:
[...]and arguments that have type float are promoted to double. These are called the default argument promotions.[...]
from the draft C++ standard section 5.2.2
Function call:
[...]a floating point type that is subject to the floating point promotion (4.6), the value of the argument is converted to the promoted type before the call. [...]
and section 4.6
:
A prvalue of type float can be converted to a prvalue of type double. The value is unchanged
cppreference covers the default conversions for variadic function in C++ well:
- std::nullptr_t is converted to void*
- float arguments are converted to double as in floating-point promotion
- bool, char, short, and unscoped enumerations are converted to int or wider integer types as in integer promotion
We can see in C and presumably in C++ this conversion was kept around for compatibility with K&R C, from Rationale for International Standard—Programming Languages—C (emphasis mine):
For compatibility with past practice, all argument promotions occur as described in K&R in the absence of a prototype declaration, including the not always desirable promotion of float to double.
Solution 2:
As for the why part of the question, it's simple: the C (and C++) standards consider double
to be the "default" floating point type. Not float
(which is what many of us programmers default to when using floating point numbers).
This can be seen by observing:
-
3.14
is adouble
(if you want afloat
, you've got to take an extra step and append anf
) - The standard math functions take a
double
by default (for example,sin()
takes adouble
; if you want afloat
you've got to usesinf()
)
With this, it seems more "natural" that a float
would be promoted to double
in a variadic function call, given that double
is the "natural" default in the language.