web-dev-qa-db-fra.com

Spécificateur de format correct pour double dans printf

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.

Échantillon de code

#include <stdio.h>

int main()
{
   double d = 1.4;
   printf("%lf", d); // Is this wrong?
}
433
Leopard

"%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.

561
Jerry Coffin

É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é dans printf

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.
59
mloskot

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.

19
vitaut

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.

10
AnT

%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.

8
Frédéric Hamidi