Quel est le spécificateur de format correct pour double
dans printf? Est-ce %f
ou est-ce %lf
? Je crois que c'est %f
, mais je ne suis pas sûr.
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
"%f"
est le format correct (ou au moins un) correct pour un double. There is pas de format pour un float
, car si vous essayez de passer un float
à printf
, il sera promu à double
avant printf
le reçoit1. "%lf"
est également acceptable selon le standard actuel - la l
n'a pas d'effet si elle est suivie du spécificateur de conversion f
(entre autres).
Notez que c’est un endroit où les chaînes de format printf
diffèrent considérablement des chaînes de format scanf
(et fscanf
, etc.). Pour la sortie, vous passez un valeur, qui passera de float
à double
lorsqu’il sera passé en tant que paramètre variadique. Pour l’entrée, vous passez un pointeur, qui n’est pas promu, vous devez donc indiquer à scanf
si vous souhaitez lire un float
ou un double
, Donc, pour scanf
, %f
signifie que vous voulez lire un float
et %lf
signifie que vous voulez lire un double
(et, pour ce que cela vaut, pour a long double
, vous utilisez %Lf
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 n'inclut pas de prototype, les promotions d'entier sont effectuées sur chaque argument et les arguments de type float sont promus doublés. Celles-ci sont appelées les promotions d'arguments 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 sont soumis à des promotions par défaut avant d’être reçus par la fonction.
Étant donné le standard C99 (à savoir, le N1256 brouillon), les règles dépendent du type de fonction: fprintf (printf, sprintf, ...) ou scanf.
Voici les parties pertinentes extraites:
Avant-propos
Cette deuxième édition annule et remplace la première édition, ISO/IEC 9899: 1990, telle que modifiée et corrigée par ISO/IEC 9899/COR1: 1994, ISO/IEC 9899/AMD1: 1995 et ISO/IEC 9899/COR2: 1996. Les principaux changements par rapport à l'édition précédente incluent:
%lf
spécificateur de conversion autorisé dansprintf
7.19.6.1 La fonction
fprintf
7 Les modificateurs de longueur et leur signification sont:
l (ell) Spécifie que (...) n'a aucun effet sur un spécificateur de conversion a, A, e, E, f, F, g ou G suivant.
L Spécifie qu'un spécificateur de conversion a, A, e, E, f, F, g ou G suivant s'applique à un double argument long.
Les mêmes règles que celles spécifiées pour fprintf
s'appliquent à printf
, sprintf
et à des fonctions similaires.
7.19.6.2 La fonction
fscanf
11 Les modificateurs de longueur et leur signification sont:
l (ell) Spécifie que (...) qu'un spécificateur de conversion a, A, e, e, f, f, g ou G suivant s'applique à un argument dont le type est pointé en double;
L Spécifie qu'un spécificateur de conversion a, A, e, E, f, g ou G suivant s'applique à un argument dont le type est pointé sur long double.
12 Les spécificateurs de conversion et leur signification sont les suivants: a, e, f, g Correspond à un nombre à virgule flottante signé en option, (...)
14 Les spécificateurs de conversion A, E, F, G et X sont également valides et se comportent de la même manière que, respectivement, a, e, f, g et x.
En bref, pour fprintf
, les spécificateurs et types correspondants sont spécifiés:
%f
-> double%Lf
-> long double.et pour fscanf
c'est:
%f
-> float%lf
-> double%Lf
-> long double.Il peut s'agir de %f
, %g
ou %e
, en fonction de la manière dont vous souhaitez formater le numéro. Voir ici pour plus de détails. Le modificateur l
est requis dans scanf
avec double
, mais pas dans printf
.
Le format correct de printf
pour double
est %lf
, exactement comme vous l'avez utilisé. Il n'y a rien de mal avec votre code.
Le format %lf
in printf
n'était pas pris en charge par les anciennes versions (antérieures à C99) du langage C, ce qui créait une "incohérence" superficielle entre les spécificateurs de format pour double
dans printf
et scanf
. Cette incohérence superficielle a été corrigée dans C99.
Ainsi, en C moderne, il est parfaitement logique de préférer utiliser %f
avec float
, %lf
avec double
et %Lf
avec long double
de manière cohérente dans les deux printf
et scanf
.
%Lf
(notez que la majuscule L
) est le spécificateur de format pour longs doubles .
Pour la lecture simple doubles
, %e
, %E
, %f
, %g
ou %G
fera l'affaire.