c++ variadic templates
¿Por qué printf() promueve un flotador a un doble? (4)
De una question anterior:
Si intenta pasar un
float
aprintf
, se promocionará aldouble
antes de queprintf
reciba
printf()
es una función variada ¿verdad?
Entonces, ¿una función variadic promueve un argumento
float
a un
double
antes de pasarlo?
Dado un prototipo de función, el tipo flotante solo se promueve automáticamente 1 cuando se usa en argumentos finales. La función de impresión utiliza esos:
int printf(const char * restrict format, ...);
1
(Citado de: ISO / IEC 9899: 201x 6.5.2.2 Llamadas de función)
6. las promociones de enteros se realizan en cada argumento, y los argumentos que tienen tipo flotante se promueven al doble.
Estos se denominan promociones de argumento por defecto.
7. Las promociones de argumento predeterminadas se realizan en argumentos finales.
En cuanto a la parte del por
qué
de la pregunta, es simple: los estándares C (y C ++) consideran que el
double
es el tipo de punto flotante "predeterminado".
No
float
(que es lo que muchos de nosotros los programadores usamos por defecto cuando usamos números de coma flotante).
Esto se puede ver observando:
-
3.14
es undouble
(si quieres unfloat
, tienes que dar un paso extra y agregar unaf
) -
Las funciones matemáticas estándar toman un
double
por defecto (por ejemplo,sin()
toma undouble
; si quieres unfloat
tienes que usarsinf()
)
Con esto, parece más "natural" que un
float
sea promovido a
double
en una llamada de función variable, dado que
double
es el valor predeterminado "natural" en el lenguaje.
Porque el estándar (C99 o C11 ) lo dice. Ver respuesta por 2501 .
Hay varias razones pragmáticas para eso: historial (las primeras implementaciones de C se han utilizado para la programación del sistema, donde las operaciones de punto flotante no importan), y el hecho de que en los procesadores actuales (tableta, escritorio, servidor ...), aritmética las operaciones en
double
son casi tan eficientes como
float
(pero algunos microcontroladores baratos no tienen FPU, o solo pueden agregar
float
por hardware, y requieren una biblioteca para cada operación en
double
).
Por último, supongo que tal regla permite
convenciones de llamada
y
ABI
s un poco más simples.
Piense en
float
como una especie de
short double
(que por supuesto es
ilegal
en C).
Un
float
es útil principalmente cuando necesita compactar memoria (y puede permitirse la pérdida de precisión).
Ver también
http://floating-point-gui.de/
para más.
Sí, los argumentos flotantes a la función variadic se promueven al doble.
El
borrador de la
sección
estándar C99
6.5.2.2
Llamadas de función dice:
[...] y los argumentos que tienen tipo float se promueven al doble. Estos se denominan promociones de argumento por defecto. [...]
del
borrador de la
sección
estándar de C ++
5.2.2
Llamada de función:
[...] un tipo de punto flotante que está sujeto a la promoción de punto flotante (4.6), el valor del argumento se convierte al tipo promocionado antes de la llamada. [...]
y sección
4.6
:
Un valor de tipo flotante se puede convertir en un valor de tipo doble. El valor no ha cambiado.
cppreference cubre las conversiones predeterminadas para la función variadic en C ++ bien:
- std :: nullptr_t se convierte a void *
- los argumentos flotantes se convierten en dobles como en la promoción de punto flotante
- Las enumeraciones bool, char, short y unscoped se convierten a tipos enteros int o más amplios como en la promoción de enteros
Podemos ver en C y presumiblemente en C ++, esta conversión se mantuvo por compatibilidad con K&R C , de Razonamiento para el estándar internacional — Lenguajes de programación — C ( énfasis mío ):
Por compatibilidad con la práctica anterior, todas las promociones de argumentos ocurren como se describe en K&R en ausencia de una declaración de prototipo, incluida la promoción no siempre deseable de flotación para duplicar .