Tout d'abord, comme évoqué dans plusieurs autres réponses mais pas, à mon avis, il définit assez clairement: Il n'est de travailler pour fournir un nombre entier dans la plupart des contextes où une fonction de la bibliothèque prend un double
ou float
argument. Le compilateur insère automatiquement une conversion. Par exemple, sqrt(0)
est bien défini et ne se comportent exactement comme sqrt((double)0)
, et la même chose est vraie pour tout autre type entier expression-là.
printf
est différent. Il est différent parce qu'il prend un nombre variable d'arguments. Son prototype de fonction est
extern int printf(const char *fmt, ...);
Par conséquent, lorsque vous écrivez
printf(message, 0);
le compilateur n'avons pas toutes les informations à propos de ce type printf
s'attend à ce que le second argument. Il a seulement le type de l'argument expression, c'est - int
, pour aller par. Par conséquent, contrairement à la plupart des fonctions de la bibliothèque, c'est sur, vous, le programmeur, afin de s'assurer que l'argument de la liste correspond aux attentes de la chaîne de format.
(Les compilateurs modernes pouvez les regarder dans un format de chaîne et de vous dire que vous avez une incompatibilité de type, mais ils ne vont pas commencer à insérer les conversions à accomplir ce que vous voulez dire, parce que mieux votre code doit pause maintenant, lorsque vous remarquerez, que des années plus tard, quand reconstruite avec un moins utile compilateur.)
Maintenant, l'autre moitié de la question: étant Donné que (int)0 et (float)0,0, sur la plupart des systèmes modernes, tous les deux représentés sur 32 bits qui sont toutes à zéro, pourquoi ne pas travailler de toute façon, par hasard? La norme C juste dit "ce n'est pas nécessaire pour le travail, vous êtes sur votre propre", mais permettez-moi de préciser les deux raisons les plus courantes pourquoi ça ne marcherait pas; ce sera probablement vous aider à comprendre pourquoi il n'est pas nécessaire.
Tout d'abord, pour des raisons historiques, lorsque vous passez une float
grâce à une liste d'arguments variable, il obtient promu à l' double
, ce qui, sur la plupart des systèmes modernes, est 64 bits de large. Donc, printf("%f", 0)
passe seulement 32 zéro des bits à un appelé attend 64 d'entre eux.
La seconde, tout aussi importante raison est que à virgule flottante fonction des arguments peuvent être passés dans un autre lieu que les arguments entiers. Par exemple, la plupart des Processeurs distincts enregistrer des fichiers pour les entiers et les valeurs à virgule flottante, de sorte qu'il pourrait être une règle que les arguments de 0 à 4 go dans les registres r0 à r4 si elles sont des nombres entiers, mais f0 à f4 si ils sont à virgule flottante. Donc, printf("%f", 0)
regarde dans le registre de la f1 pour que zéro, mais ce n'est pas là du tout.