À quoi sert le spécificateur de format correct double
dans printf? Est-ce %f
ou est-ce %lf
? Je le crois %f
, mais je n'en suis pas sûr.
Exemple de code
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
"%lf"
n'est pas défini; dans les bibliothèques C99 et C11, il est défini comme étant identique à"%f"
.%lf
est le spécificateur de format correct pourdouble
. Mais c'est devenu ainsi en C99. Avant cela, il fallait utiliser%f
.Réponses:
"%f"
est le (ou au moins un) format correct pour un double. Il n'y a pas de format pour afloat
, car si vous essayez de passerfloat
àprintf
, il sera promudouble
avant de leprintf
recevoir 1 ."%lf"
est également acceptable selon la norme actuelle - lel
est spécifié comme n'ayant aucun effet s'il est suivi par lef
spécificateur de conversion (entre autres).Notez que c'est un endroit où les
printf
chaînes de format diffèrent considérablement des chaînes de formatscanf
(etfscanf
, etc.). Pour la sortie, vous transmettez une valeur , qui sera promue defloat
àdouble
lorsqu'elle est transmise en tant que paramètre variadic. Pour l'entrée, vous passez un pointeur , qui n'est pas promu, vous devez donc direscanf
si vous voulez lire unfloat
ou undouble
, donc pourscanf
, cela%f
signifie que vous voulez lire unfloat
et%lf
signifie que vous voulez lire undouble
(et, pour ce que c'est vaut, pour unlong double
, vous utilisez%Lf
pourprintf
ouscanf
).1. C99, §6.5.2.2 / 6: "Si l'expression qui dénote la fonction appelée a un type qui n'inclut pas de prototype, les promotions entières sont effectuées sur chaque argument et les arguments de type float sont promus au double. Ce sont les promotions d'argument par défaut. " En C ++, le libellé est quelque peu différent (par exemple, il n'utilise pas le mot "prototype") mais l'effet est le même: tous les paramètres variadiques subissent des promotions par défaut avant d'être reçus par la fonction.
la source
g++
rejette%lf
lors de la compilation avec-Wall -Werror -pedantic
:error: ISO C++ does not support the ‘%lf’ gnu_printf format
l
était une extension. Les normes C99 / 11 et C ++ 11 nécessitent l'implémentation pour le permettre.scanf
ne fait défautdouble
de représenté par%lf
: il se plaint que prévufloat *
et a trouvédouble *
avec juste%f
.scanf
prend des pointeurs vers où stocker ce qu'il lit, a donc besoin de savoir quelle est la taille de l'espace visé , tandis queprintf
prend les valeurs elles-mêmes, et "promotions d'argument par défaut" signifient que les deux finissent pardouble
s, donc lel
est essentiellement facultatif.Compte tenu de la norme C99 (à savoir le projet N1256 ), les règles dépendent du type de fonction: fprintf (printf, sprintf, ...) ou scanf.
Voici les parties pertinentes extraites:
Les mêmes règles spécifiées pour
fprintf
appliquer pourprintf
,sprintf
et des fonctions similaires.La longue histoire courte, pour
fprintf
les spécificateurs suivants et les types correspondants sont spécifiés:%f
-> double%Lf
-> long double.et
fscanf
c'est:%f
-> flotter%lf
-> double%Lf
-> long double.la source
Cela peut être
%f
,%g
ou%e
selon la façon dont vous souhaitez que le nombre soit formaté. Voir ici pour plus de détails. Lel
modificateur est requis dansscanf
avecdouble
, mais pas dansprintf
.la source
l
modificateur (en minuscules) concerne les types entiers ( cplusplus.com/reference/clibrary/cstdio/printf ) et lesL
types à virgule flottante. De plus, leL
modificateur attend unlong double
, pas un simpledouble
.l
n'est pas nécessaireprintf
pourdouble
.Le format
%lf
est unprintf
format parfaitement correct pourdouble
, exactement comme vous l'avez utilisé. Il n'y a rien de mal avec votre code.Le format
%lf
inprintf
n'était pas pris en charge dans les anciennes versions (antérieures à C99) du langage C, ce qui créait une "incohérence" superficielle entre les spécificateurs de format pourdouble
inprintf
etscanf
. Cette incohérence superficielle a été corrigée dans C99.Vous n'êtes pas obligé d'utiliser
%lf
avecdouble
inprintf
. Vous pouvez également l'utiliser%f
, si vous préférez (%lf
et%f
sont équivalents enprintf
). Mais dans le C moderne, il est parfaitement logique de préférer utiliser%f
avecfloat
,%lf
avecdouble
et%Lf
aveclong double
, de manière cohérente dansprintf
etscanf
.la source
scanf()
,"%f"
,"%lf"
correspondre à unefloat *, double *
, et nonfloat, double
comme le laisse entendre la dernière ligne.%Lf
(notez la majusculeL
) est le spécificateur de format pour les longs doubles .Pour plaine
doubles
, que ce soit%e
,%E
,%f
,%g
ou%G
fera.la source
%g
et%G
?