J'ai un entier non signé mais quand je l'imprime en utilisant% d il y a parfois une valeur négative là-bas? P>
3 Réponses :
Cela devrait fonctionner:
unsigned int a; printf("%u\n", a);
impression Pour imprimer des nombres non signés, utilisez Cela se produit à cause du moyen de C pour gérer des arguments variables. Le compilateur déclenche simplement les valeurs de la pile (typé comme C'est pourquoi vous devez fournir le format String - C n'a aucun moyen de RTTI A > ou une «classe de base» (% d code> lira l'entier comme un nombre décimal signé, quel que soit son type défini. P>
% u code>. p>
vide * code> et pointant sur la pile d'appels) et
printf code> doit déterminer ce que les données contiennent de la chaîne de format que vous donnez à. p>
objet code> en Java, par exemple) pour obtenir un
générique ou prédéfini> tostring code> de. p>
Nitpick: C est appel à valeur, de sorte que le compilateur tire la valeur des arguments, pas des pointeurs. Vous ne passez pas les pointeurs à des valeurs (printf ("% u", et myvariable);), vous passez des valeurs directement (printf ("% u", myvariable););
@Liranuna - La mise en œuvre des fonctions Varargs n'est pas spécifiée, ce qui est pourquoi ni #define VA_COPY (DEST, SRC) DEST = SRC code> ou
#define VA_COPY (DEST, SRC) MemcPy (DEST , src, taille de (Va_list)) code> est un remplacement portable pour le
VA_COPY code> macro sur les systèmes où il n'est pas fourni. L'un d'entre eux peut travailler, mais qui sait quoi?
Ok alors, "le plus communément mis en œuvre par ...". Il n'y a pas vraiment un autre moyen efficace de déplacer une quantité inconnue de données dans laquelle chacun des arguments a une taille variable ... Un pointeur est une taille constante et le compilateur a déjà les informations de taille de l'appelant. VA_COPY code> est un aswell intrinsèque.
Liranuna: Bien sûr, poussez-la (dans le sens des instructions de poussoir ASM) à la pile. VA_COPY n'a pas besoin d'être intrinsèque, il doit connaître les détails de la mise en œuvre qui varient en fonction des implémentations.
Ah, je vois que si vous étirez «Passez un pointeur sur la pile» pour signifier le registre indiquant le cadre de pile actuel, vous auriez raison, mais c'est trop d'étirement.
@Roger: Oui, poussez-le - puis fournissez Printf avec le pointeur à l'emplacement de l'argument sur la pile - car l'argument est de taille dynamique. Je ne comprends pas pourquoi vous discutez de quelque chose que nous sommes d'accord. L'anglais n'est pas ma langue maternelle, alors je suis désolé s'il y a malentendu.
Nous ne sommes pas d'accord. Combien de "pointeurs" pensez-vous que Printf devient pour printf (s, a, b, c)? Dire que la pile est "fournie par un pointeur" suffit d'un stretch pour être considéré comme un problème clair - à ce point que vous n'écrivez pas C. (pourrait certainement être une question de langue.)
Mais c'est ainsi que chaque appel de fonction se comporte qui n'utilise pas de registres. Ce n'est pas quelque chose de spécifique aux fonctions Printf ou Vararg, en fait. Le cadre de pile de la fonction actuelle commence quelque part, et là, ou directement en dessous, constituera les arguments entrants, sur de nombreuses architectures de toute façon.
C'est dépendant de la mise en œuvre s'il y a une pile du tout. Les arguments sont juste. Dans la pratique (comme le dit Liranuna et que tout le monde sait très bien), presque chaque convention d'appel, vous rencontrerez jamais avoir un moyen de transmettre une pile Pointer i>, même si c'est par le processeur lui-même ayant un registre dédié que pour cette fin. Ce n'est pas nécessairement le cas que tous les arguments sont transmis sur la pile - certaines conventions appelantes passent les premiers dans des registres. Cependant, c'est un PITA mettant en œuvre des varargs avec une telle convention appelante, alors je ne voudrais donc pas blâmer quiconque qui met tous les varargs sur la pile :-)
X64 ABI passe quelques arguments de printf dans des registres, de sorte que toute explication impliquant la pile est un peu faux
% d signifie que PrintF interprétera la valeur sous forme d'INT (qui est signé). Utilisez% u s'il s'agit d'un non signé INT. p>
Voyez si votre compilateur a une option pour avertir de ce type d'erreur. C'est -wformat avec GCC.
Dupliqué possible de Comment puis-je imprimer une valeur maximale d'un non signé Entier?