Correct spécificateur de format pour le double en printf
-
27-09-2019 - |
Question
Quel est le spécificateur de format correct pour double
à printf? Est-il ou est-il %f
%lf
? Je crois qu'il est %f
, mais je ne suis pas sûr.
Exemple de code
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
La solution
"%f"
est la (ou au moins une) format correct pour un double. Il pas de format pour un float
, parce que si vous essayez de passer un float
à printf
, il sera promu double
avant printf
reçoit 1 . "%lf"
est également acceptable selon la norme actuelle. - le l
est spécifié comme sans effet si elle est suivie par le spécificateur de conversion de f
(entre autres)
Notez que c'est un endroit que les chaînes de format printf
diffèrent sensiblement des chaînes de format scanf
(et fscanf
, etc.). Pour la sortie, vous passez valeur , qui sera promu de float
à double
lorsqu'il est passé en tant que paramètre variadique. Pour l'entrée vous passez pointeur , qui n'est pas promu, vous devez dire scanf
si vous voulez lire un float
ou un double
, donc pour scanf
, des moyens de %f
que vous voulez lire un float
et des moyens de %lf
vous voulez lire un double
(et, pour ce que ça vaut, pour un long double
, vous utilisez %Lf
soit pour printf
ou scanf
).
1. C99, §6.5.2.2 / 6: « Si l'expression qui désigne la fonction appelée a un type qui ne comprend pas un prototype, les promotions entières sont effectuées sur chaque argument, et les arguments qui ont de type float sont promus à doubler. on les appelle les promotions d'argument par défaut « . En C ++ le libellé est quelque peu différente (par exemple, il n'utilise pas le mot « prototype »), mais l'effet est le même: tous les paramètres par défaut variadique subissent des promotions avant qu'ils ne soient reçus par la fonction.
Autres conseils
Compte tenu de la norme C99 (à savoir le N1256 projet) , les règles dépendent du la fonction type: fprintf (printf, sprintf, ...) ou scanf
.Voici les parties pertinentes extraites:
Avant-propos
Cette deuxième édition annule et remplace la première édition, ISO / CEI 9899: 1990, tel que modifié et corrigé par l'ISO / CEI 9899 / COR1: 1994, ISO / CEI 9899 / AMD1: 1995 et ISO / CEI 9899 / COR2 : 1996. Des changements majeurs de l'édition précédente comprennent:
- spécificateur de conversion
%lf
autorisés dansprintf
7.19.6.1 La fonction
fprintf
7 Les modificateurs de longueur et leur signification sont:
l (ell) Indique que (...) n'a pas d'effet sur une suite a, A, e, e, f, f, g, ou spécificateur de conversion G.
L Spécifie qu'une suite a, A, E, E, F, F, G, ou G spécificateur de conversion applique à un long double argument.
Les mêmes règles spécifiées pour fprintf
demander printf
, sprintf
et des fonctions similaires.
7.19.6.2 La fonction
fscanf
11 Les modificateurs de longueur et leur signification sont:
l (ell) Indique que (...) qu'une suite a, A, e, e, f, f, g, ou spécificateur de conversion G applique à un argument de pointeur de type à doubler;
L Spécifie qu'une suite a, A, E, E, F, F, G, ou G conversion spécificateur applique à un argument avec le pointeur de type à long double.
12 Les indicateurs de conversion et leurs significations sont: a, e, f, g correspond à un nombre à virgule flottante éventuellement signé, (...)
14 Les indicateurs de conversion A, E, F, G et X sont également valables et comportent le même que, respectivement, a, e, f, g et x.
La longue histoire courte, pour fprintf
les spécificateurs et les types correspondants sont spécifiés:
-
%f
-> double -
%Lf
-.> Long double
et fscanf
il est:
-
%f
-> float -
%lf
-> double -
%Lf
-.> Long double
Le format printf
correct pour double
est %lf
, exactement comme vous l'avez utilisé. Il est faux de rien avec votre code.
Format %lf
en printf
n'a pas été pris en charge dans les anciennes versions (pré-C99) du langage C, qui a créé « incohérence » superficielle entre spécificateurs de format pour double
dans printf
et scanf
. Cette incohérence superficielle a été corrigé dans C99.
Donc, en C moderne, il est parfaitement logique de préférer utiliser %f
avec float
, %lf
avec double
et %Lf
avec long double
toujours dans les deux printf
et scanf
.
Pour une double vous pouvez simplement utiliser %lf
ou vous pouvez utiliser une des actions suivantes selon votre préférence
%e
ou %E
pour les valeurs en format exponentielle
%g
ou %G
soit pour la notation normale ou exponentielle, selon le plus approprié pour son ampleur.
En savoir plus sur ici Liste des tous les spécificateur de format en C