Étrange sortie printf

J’ai exécuté le code suivant

#include  int main() { printf("%f\n", 9/5); } 

Sortie: 0.000000

pourquoi pas 1 ?

si j’écris printf("%f %f %d %d\n", (float)9/5, 4, sizeof(float), sizeof(int));

alors la sortie est 1.800000 0.000000 4 59

pourquoi pas 1.800000 4 4 4

sur ma machine le sizeof (float) est 4

Merci d’avance

En effet, votre printf format printf ne correspond pas à ce que vous lui avez transmis:

9/5 est de type int . Mais printf attend un float .

Vous devez donc soit le lancer dans un float, soit en faire un float:

 printf("%f\n", (float)9/5); printf("%f\n", 9./5); 

Quant à la raison pour laquelle vous obtenez 0.0 , c’est parce que printf() lit la représentation binary de 1 (un entier) et l’imprime sous forme de float . Ce qui se trouve être une petite valeur dénormalisée très proche de 0.0 .

EDIT: Il y a aussi quelque chose qui se passe avec la promotion du type sur varargs.

Dans les fonctions vararg, float est promu double . Donc, dans ce cas, printf() attend en fait un paramètre 64 bits contenant un double . Mais vous ne lui avez passé qu’un opérande de 32 bits, de sorte qu’il lit en fait un extra de 32 bits dans la stack (qui se trouve être nul dans ce cas) – un comportement encore plus indéfini.

Regardons ce qui se passe au niveau du bit:

  • Vous calculez 9/5, les deux nombres int -> Ceci vaut 1 (encore int ) (disons 32 bits) ce qui est:

     0000 0000 0000 0000 0000 0000 0000 0001 
  • Vous le poussez comme argument de printf

  • Vous indiquez à printf d’obtenir 32 bits de données à partir d’arguments et de l’imprimer sous forme de nombre à virgule flottante.
  • printf lit le numéro que j’ai écrit ci-dessus et l’imprime comme s’il était codé avec IEEE 754. Le résultat est presque 0.

Vous pouvez voir ici la conversion:

 0000 0000 0000 0000 0000 0000 0000 0001 

évalue à

 1.4012984e-45 

Quant à pourquoi

 printf("%f %f %d %d\n", (float)9/5, 4, sizeof(float), sizeof(int)); 

ne produit pas ce que vous attendez, la raison en est que l’argument 4 est un int , qui est de 4 octets (sur votre ordinateur). En raison de la promotion des arguments, %f s’attend à un double qui est de 8 octets. C’est le même problème que ci-dessus.

L’utilisation de spécificateurs de format incorrects dans printf est UB.

  printf("%f %f %zu %d\n", (float)9/5, 4.0, sizeof(float), sizeof(int)); 

donne la sortie correcte.

Si vous construisez avec GCC, vous devez activer tous les avertissements avec -Wall et les lire attentivement.

La raison pour laquelle vous obtenez un résultat “étrange” est que vous avez violé les conditions préalables de printf (en passant des arguments dont les types ne correspondent pas aux spécifications de format), et une fois que vous l’avez fait, printf est libre de faire ce qu’il veut, y compris en plantant, en imprimant des déchets, ou faire fondre votre CPU.

9/5 est un entier mais vous essayez de l’imprimer avec “% f”. C’est la source du problème. Basculez vers 9.0 / 5 ou “% d” et vous obtiendrez la bonne réponse.

(float) 9/5 lance seulement 9 pas le résultat de 9/5. Donc, l’opération / n’est pas une opération entière à ce stade. (float) (9/5) donnera le résultat 1.00000.

Essayez de comstackr avec tous les avertissements, et cela vous dira probablement beaucoup de ce qui ne va pas.

Par exemple, sur un système Linux 64 bits, en compilant avec gcc -Wall, je reçois:

 pf.c: In function 'main': pf.c:6:2: warning: format '%f' expects argument of type 'double', but argument 3 has type 'int' [-Wformat] pf.c:6:2: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat] pf.c:6:2: warning: format '%d' expects argument of type 'int', but argument 5 has type 'long unsigned int' [-Wformat] 

Comme mentionné ci-dessus, vous avez besoin des spécificateurs de format appropriés. L’utilisation des spécificateurs de format et du casting appropriés donne:

 #include  #include  int main(int argc, char **argv) { printf("%f %f %lu %lu\n",(float)(9/5),(float)4,sizeof(float),sizeof(int)); return 0; } 

donne:

 snits@perelman:~/proj/c=>./pf 1.000000 4.000000 4 4