c++ c floating-point printf variadic-functions

c++ variadic templates



¿Por qué printf() promueve un flotador a un doble? (4)

De una question anterior:

Si intenta pasar un float a printf , se promocionará al double antes de que printf 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:

  1. 3.14 es un double (si quieres un float , tienes que dar un paso extra y agregar una f )
  2. Las funciones matemáticas estándar toman un double por defecto (por ejemplo, sin() toma un double ; si quieres un float tienes que usar sinf() )

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 .