10
votes

C Printf en utilisant% d et% f

Je travaillais sur ce programme et j'ai remarqué que l'utilisation de% F pour un double et% D pour un flotteur me donne quelque chose de complètement différent. Tout le monde sait pourquoi cela se produit? XXX PRE>

Ceci est la sortie P>

float = -1610612736
double = 190359837192766135921612671364749893774625551025007120912096639276776057269784974988808792093423962875123204096.0000


1 commentaires

Voir la spécification C11 pour §7.21.6.1 Le Printf < / Code> Fonction (ou la spécification POSIX pour FPRRINTF () ) Pour plus d'informations sur l'utilisation d'utiliser printf () correctement et aussi §6.5.2.2 Appels de fonction ¶6 et 7 à propos de la manière dont les arguments de point flottant sont transmis aux fonctions variadiques. Les compilateurs C modernes tels que GCC et Clang fournissent facilement des diagnostics étendus pour des incompatibles au format - vous devez activer les avertissements de compilation.


4 Réponses :


3
votes

Cela concerne les représentations internes des données. Vous essayez d'imprimer un flotteur comme s'il s'agissait d'INT, qui a une représentation interne (binaire) complètement différente.

Le cas double est similaire. Vous avez probablement des ordures (toutes les données) après la variable de flotteur. Cette poubelle est interprétée comme faisant partie de la double valeur.


0 commentaires

4
votes

En raison de la façon dont les paramètres variables fonctionnent, c ne contient aucune idée du type de valeur que vous en passez à autre que % d et % f . Lorsque vous passez dans un paramètre variable, vous faites fondamentalement (vide *) et myvalue car ni le compilateur, ni la fonction au moment de l'exécution ne peuvent déterminer le type de variable sauf pour ce qui est donné dans la chaîne de formatage . Donc, même s'il existe une conversion implicite disponible, le compilateur ne sait pas que cela est nécessaire.

Eh bien, le double est de 8 octets sur la plupart des systèmes pendant que le flotteur est de 4 octets. Les deux types ne sont donc pas compatibles binaires tels quels. Et c'est comme essayer d'interpréter une chaîne comme un double, ou un autre type incompatible.


3 commentaires

Correct, mais il ne s'agit pas vraiment de la compatibilité entre float et double spécifiquement. En fait, des arguments variadiques de float sont toujours favorisés à double avant de passer, ce qui signifie que float n'est pas impliqué dans quoi que ce soit ici. Les deux valeurs transmises à printf ont double type. À l'intérieur du premier est interprété comme un int (en raison de % d spécificateur). L'incompatibilité entre int et double est ce qui cause le comportement non défini non défini.


Avec une fonction variadique telle que printf () , tout float La valeur passée dans le cadre de la liste d'arguments variable est automatiquement convertie en double (voir C11 §6.5.2.2 Appels de fonction ¶6 & 7 ).


Je ne peux vraiment pas être d'accord avec "Vous faites fondamentalement (void *) et myvalue " - les valeurs sont transmises comme des valeurs et non comme des pointeurs.



6
votes

% d représente une décimale et il s'attend à un argument de type int (ou un type d'entiers signé plus petit qui est ensuite promu). Types de points flottants float et Double Les deux sont passés de la même manière (promu au double ) et les deux utilisent les deux % f < / code>. En C99, vous pouvez également utiliser % LF pour signifier la taille plus grande de double , mais ceci est purement cosmétique (remarquez qu'avec scanf aucune promotion ne se produit et cela fait en réalité une différence).


1 commentaires

Eh bien, c'est vrai CODEPAD.ORG/LABE8LGY Mais je me demande comment cela fonctionne réellement ..



1
votes

% D imprime un entier, votre PrintF interpréte donc votre variable A comme int.

avec GCC 3.4.6, je reçois des 0 à la fois pour les deux valeurs avec votre code (après avoir pris l'initialisation de F, une erreur de compilateur). Je soupçonne que cela a à voir avec la partie de la variable d'une variable qui est interprétée comme une étant 0, puis le compilateur est confus ... (Il y a probablement une meilleure explication, mais je ne peux pas y penser). < / p>

Utiliser% f pour les deux impressions variables 1.000000 pour les deux variables pour moi.

Vous pouvez trouver une liste des caractères de conversion près du bas de cette page:

http: / /www.exforsys.com/tatudials/c-language/maning-input-and-Output-operations-in-c.html


1 commentaires

L'erreur de compilateur associée à f est qu'elle ne peut pas être attachée à un entier (par exemple, 1.0f est bien).