Disons que j'ai le code suivant en C:
double var;
scanf("%lf", &var);
printf("%lf", var);
printf("%f", var);
Il lit la variable stdin 'var' puis s'imprime deux fois dans la sortie standard 'var'. Je comprends que vous lisiez une double variable de stdin, mais mes questions sont les suivantes:
Pour les fonctions à arguments variables telles que printf
et scanf
, les arguments sont promus; par exemple, tous les types entiers les plus petits sont promus à int
, float
est promu en double
.
scanf
prend les paramètres des pointeurs, ainsi la règle de promotion n'a aucun effet. Il doit utiliser %f
pour float*
et %lf
pour double*
.
printf
ne verra jamais un argument float
, float
est toujours promu en tant que double
. Le spécificateur de format est %f
. Mais C99 dit aussi %lf
est le même que %f
dans printf
:
C99 §7.19.6.1 La fonction
fprintf
l
(ell) Spécifie qu'uned
,i
,o
,u
,x
ouX
spécificateur de conversion s'applique à unlong int
ouunsigned long int
argument; qu'un spécificateur de conversionn
suivant s'applique à un pointeur sur unlong int
argument; qu'un spécificateur de conversionc
suivant s'applique à unwint_t
argument; qu'un spécificateur de conversions
suivant s'applique à un pointeur sur unwchar_t
argument; ou n'a aucun effet sur les éléments suivantsa
,A
,e
,E
,f
,F
,g
ouG
spécificateur de conversion.
Quand un float
est passé à printf
, il est automatiquement converti en un double
. Cela fait partie des promotions par défaut, qui s’appliquent aux fonctions ayant une liste de paramètres variables (contenant ...
), principalement pour des raisons historiques. Par conséquent, le spécificateur "naturel" pour un float
, %f
, doit fonctionner avec un argument double
. Alors le %f
et %lf
Les spécificateurs de printf
sont identiques; ils prennent tous deux une valeur double
.
Lorsque scanf
est appelé, les pointeurs sont transmis et non les valeurs directes. Un pointeur sur float
n'est pas converti en un pointeur sur double
(cela pourrait ne pas fonctionner car l'objet pointé ne peut pas changer lorsque vous modifiez le type de pointeur). Donc, pour scanf
, l'argument de %f
doit être un pointeur sur float
et l'argument de %lf
doit être un pointeur sur double
.
Dans la mesure où je lis les pages du manuel, scanf indique que le modificateur de longueur indique (dans le cas de points flottants) que l'argument est de type double plutôt que de type float, vous pouvez donc avoir 'lf, le, lg'.
En ce qui concerne l’impression, officiellement, le manuel dit que "je" ne s’applique qu’aux types entiers. Il est donc possible que cela ne soit pas pris en charge sur certains systèmes ou par certaines normes. Par exemple, je reçois le message d'erreur suivant lors de la compilation avec gcc -Wall -Wextra -pedantic
a.c:6:1: warning: ISO C90 does not support the ‘%lf’ gnu_printf format [-Wformat=]
Donc, vous voudrez peut-être vérifier si votre standard supporte la syntaxe.
Pour conclure, je dirais que vous lisez avec '% lf' et que vous imprimez avec '% f'.