C : Impression grand nombre
Prendre le suivant :
#include <stdio.h>
main() {
unsigned long long verybig = 285212672;
printf("Without variable : %llu\n", 285212672);
printf("With variable : %llu", verybig);
}
C'est la sortie du programme ci-dessus :
Without variable : 18035667472744448
With variable : 285212672
Comme vous pouvez le voir ci-dessus, lorsque printf
est passé le nombre comme une constante, il imprime un grand nombre incorrect, mais lorsque la valeur est d'abord stocké dans une variable, printf
imprime le nombre correct.
Quel est le raisonnement derrière cela?
OriginalL'auteur Andreas Grech | 2009-09-06
Vous devez vous connecter pour publier un commentaire.
Essayer
285212672ULL
; si vous l'écrire sans suffixes, vous trouverez le compilateur traite comme un régulier entier. La raison, c'est de travailler dans une variable est parce que l'entier est en train de lancer uneunsigned long long
dans l'affectation, de sorte que la valeur passée àprintf()
est le type de droit.Et avant de vous demander, non, le compilateur probablement n'est pas assez intelligent pour comprendre, à partir du
"%llu
" dans leprintf()
chaîne de format. C'est un autre niveau d'abstraction. Le compilateur est responsable de la syntaxe de la langue,printf()
sémantique ne font pas partie de la syntaxe, c'est une bibliothèque d'exécution de la fonction (pas vraiment différents de vos propres fonctions à l'exception qu'il est inclus dans la norme).Considérons le code suivant pour un int 32-bits et 64-bit unsigned long long système:
sorties:
Dans le premier cas, les deux nombres entiers de 32 bits 1 et 2 sont poussés sur la pile et
printf()
qui interprète comme un seul 64 bits ULL valeur, 2 x 232 + 1. Le2
argument est inclus par inadvertance dans l'ULL de la valeur.Dans le second, vous fait pousser le 64-bit 1-valeur et un superflu entier de 32 bits
2
, ce qui est ignoré.Noter que cette "sortir de l'étape" entre le format de votre chaîne et de vos arguments est une mauvaise idée. Quelque chose comme:
est susceptible d'impact, parce que le 32 bits
"hello"
pointeur sera consommée par le%llu
et%s
vais essayer de référence de la finale0
argument. La suite de "l'image" illustre cette (supposons que les cellules sont en 32 bits et que la chaîne "hello" est stocké à 0xbf000000.Sans ces types de données sont de la même taille - il printf() comprendre - essayez %d avec un "a".
Pax: C'est bien trop, les chaînes de caractères sont des constantes entières.
Vous avez raison @caf, mais le compilateur est de ne pas regarder à l'intérieur printf arguments. Et il ne devrait pas puisque c'est un autre niveau d'abstraction de la langue (vs bibliothèque d'exécution). J'ai mis à jour la réponse avec plus d'info.
Dans le code que vous utilisez 1 et 2, mais dans le texte que vous utilisez 0 et 1 🙂
OriginalL'auteur paxdiablo
Il est intéressant de souligner que certains compilateurs donner un avertissement utile pour ce cas - par exemple, c'est ce que GCC dit à propos de votre code:
OriginalL'auteur caf
285212672
est unint
valeur.printf
s'attend à uneunsigned long long
et vous êtes de passage unint
. Par conséquent, il va prendre plus d'octets en dehors de la pile que vous avez passé d'une valeur réelle et imprime des ordures. Lorsque vous le mettez dans ununsigned long long
variable avant de les passer à la fonction, il sera promuunsigned long long
dans l'attribution de la ligne et de vous passer cette valeur àprintf
qui fonctionne correctement.OriginalL'auteur Mehrdad Afshari
Type de données est simplement une façon d'interpréter le contenu d'un emplacement mémoire.
dans le premier cas, la valeur de la constante est stocké dans la mémoire en lecture seule de l'emplacement comme un int, le printf tente d'interpréter cette adresse que 8 octets emplacement car il est indiqué que la valeur stockée est long long dans le processus de laquelle il imprime la valeur d'ordures.
Dans le second cas printf tente d'interpréter un long valeur de 8 octets et il imprime ce qui est attendu.
OriginalL'auteur GG.