Pourquoi a-t-il scanf()
besoin du l
in " %lf
" lors de la lecture de a double
, quand printf()
peut utiliser " %f
" indépendamment du fait que son argument soit a double
ou a float
?
Exemple de code:
double d;
scanf("%lf", &d);
printf("%f", d);
c
scanf
length-modifiers
Raldi
la source
la source
&
opérateur unaire , le résultat de cette opération est un pointeur vers l'emplacement de stockage de la variable en mémoire. C'est ce pointeur qui est passé àscanf
.Réponses:
Parce que C promouvra les flottants en doubles pour les fonctions qui acceptent des arguments variables. Les pointeurs ne sont pas promus vers quoi que ce soit, vous devriez donc utiliser
%lf
,%lg
ou%le
(ou%la
en C99) pour lire en double.la source
Depuis С99, la correspondance entre les spécificateurs de format et les types d'arguments à virgule flottante en C est cohérente entre
printf
etscanf
. C'est%f
pourfloat
%lf
pourdouble
%Lf
pourlong double
Il se trouve que lorsque des arguments de type
float
sont passés en tant que paramètres variadiques, ces arguments sont implicitement convertis en typedouble
. C'est la raison pour laquelle dans lesprintf
spécificateurs de format%f
et%lf
sont équivalents et interchangeables. Dansprintf
vous pouvez "utiliser de manière croisée"%lf
avecfloat
ou%f
avecdouble
.Mais il n'y a aucune raison de le faire dans la pratique. N'utilisez pas
%f
d'printf
arguments de typedouble
. C'est une habitude répandue qui est née à C89 / 90 fois, mais c'est une mauvaise habitude. Utilisation%lf
enprintf
pourdouble
et garder%f
réservé auxfloat
arguments.la source
%f
de printf est une bonne habitude car votre code fonctionne toujours, alors que l'utilisation%lf
peut échouer si le compilateur n'a pas de bibliothèque compatible C99. Malheureusement, cette situation se produit dans la réalité.printf
etscanf
. Notez que cela n'implique pas que l'utilisation du même spécificateur de format signifie que les données écrites par a[f]printf()
peuvent être lues par[f]scanf()
. En général, en utilisant le même spécificateur de format pourscanf()
qui a été utilisé parprintf()
ne pas lire les données avec succès. Par exemple, l' espace de remplissage qui peut être inséré par unprinf()
de »"%d"
spécificateur de format sera ignorée par ce même"%d"
spécificateur de format dans unscanf()
appel.scanf
a besoin de connaître la taille des données pointées par&d
pour les remplir correctement, alors que les fonctions variadiques promeuvent les flottants en doubles (printf
je ne sais pas vraiment pourquoi), donc obtient toujours undouble
.la source
Parce que sinon, scanf pensera que vous passez un pointeur vers un flottant qui est d'une taille plus petite qu'un double, et il renverra une valeur incorrecte.
la source
L'utilisation d'un flottant ou d'une valeur double dans une expression C entraînera une valeur double de toute façon, donc printf ne peut pas faire la différence. Alors qu'un pointeur vers un double doit être explicitement signalé à scanf comme distinct d'un pointeur à float, car ce que le pointeur pointe est ce qui compte.
la source
float
valeurs étaient automatiquement promuesdouble
dans les expressions. Cette règle a été abandonnée dans la norme C. En général, ellefloat
n'est pas promuedouble
dans les expressions. Il n'est promu quedouble
lorsqu'il est passé en tant qu'argument variadique, ce qui se passe dans ce cas.