Printf et type de variables

Résolu/Fermé
Jork - 7 nov. 2012 à 06:15
 Jork - 7 nov. 2012 à 19:46
Bonjour,
j'ai récemment décidé de me mettre au C et je bloque sur ceci

#include <stdio.h>
int main(void)
{
        char a = 127;
        printf("a(127) : %u\n",a);
        a++;
        printf("a(128) : %u\n",a);
        a = 255;
        printf("a(255) : %u\n",a);
        a++;
        printf("a(0) : %u\n",a);
}

--------------------------
En sortie j'ai :
a(127) : 127
a(128) : 4294967168
a(255) : 4294967295
a(0) : 0



Je sais bien que je devrais utiliser le type unsigned char pour avoir des résultats cohérents, mais j'aimerais comprendre pourquoi dans cet exemple tant que je suis dans les valeurs "légales" du type char, printf m'affiche bien le résultat souhaité, alors qu'une fois en dehors la fonction va me chercher 3 autres octets remplis de 1 si je comprend bien.

Merci.

2 réponses

KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
7 nov. 2012 à 06:46
"alors qu'une fois en dehors la fonction va me chercher 3 autres octets remplis de 1 si je comprend bien."
De quoi tu parles ?

Le char est représenté sur 8 bits, ce qui signifie en particulier que de 128 à 255, le premier bit est à 1, ce qui correspond dans la plupart des représentations des nombres à une valeur négative.

255 correspond donc à -1, et comme on force l'affichage à un unsigned int (%u) on rajoute 2^32 au résultat, soit -1+2^32=4 294 967 295

Pareil pour 128 qui donne -128+2^32=4 294 967 168
0
De quoi tu parles ?
J'entendais pas légale les valeur de -128 -> 127 pour un type signed char, mais effectivement ton explication semble tout a fait logique, je ne voyais pas ça dans ce sens la.
De même 127 + 2^32 nous donne bien 127 ce qui explique le résultat que j'ai obtenu, mais je ne saisi toujours pas pourquoi on ajoute ce 2^32.
Je m'attendais à ce que la fonction prenne mes 8bit et m'affiche ça tel quel sans se préoccupé du premier bit étant donné que je lui demande de m'afficher ça comme un nombre non signé.
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
7 nov. 2012 à 07:56
En fait, on n'ajoute pas vraiment 2^32, mais comme un unsigned int est codé sur 32 bits, il n'y a aucune différence entre x et x+k*2^32, car ils ont la même représentation binaire.
-1 c'est la valeur que l'on obtiendrait si on interprétait la représentation binaire avec un signed int, mais avec la même représentation en binaire, cette valeur vaut 4 294 967 295 pour un unsigned int.
Inversement 4 294 967 295 n'a aucun sens pour un signed int, puisque la valeur maximale est 2 147 483 647. Il s'agit "simplement" d'une histoire d'interprétation des bits.
0
Ok, donc pour être sur de bien comprendre,
quand je déclare mon char j'ai un espace de 8bits réservé, ensuite quand je demande à printf de m'afficher une variable qui est censée être codée sur 32bits mais que je lui en passe une de 8bits seulement, le problème est résolu en ajoutant la valeur de mon char à une variable de 32bits initialisé à 0 ?
Ensuite si tout ceci est correct, c'est bien le compilateur qui se charge de tout ça, qui va vérifier que mon char est signed ou non ? (puisque si j'ai bien compris en C les types ne servent qu'au compilateur, on a plus aucune trace de cette notion lors de l'exécution ?)
Et toujours dans l'hypothèse ou c'est juste, on pourrait donc imaginer qu'un autre compilateur prenne mes 8bits tel quel et remplisse les 24bits manquant avec des 0 ?
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
7 nov. 2012 à 19:08
Là il faudrait voir avec des spécialistes du C que je ne suis pas, mais un compilateur est censé respecté le langage qu'il compile, donc normalement tous les compilateurs C digne de ce nom feront la même chose. Le char est signé, donc le bit de signe est propagé et on ne compte donc que 7 bits de valeur ce qui permet d'avoir la même valeur sur 8 bits ou 32 bits. Mais ce que tu fais c'est que tu passes de signed à unsigned, ce n'est pas le même format de donnée, ce que tu obtiens est plus un effet de bord d'une erreur de programmation, qu'une conversion mal codée dans le compilateur.
0
D'accord ce me semble un peu plus clair, je te remercie pour ta patience :)
0
armasousou Messages postés 1270 Date d'inscription dimanche 16 août 2009 Statut Membre Dernière intervention 30 décembre 2016 83
7 nov. 2012 à 19:12
char sert a definir des CARACTERES, même si on peut l'utiliser pour des nombres et autres subtilités (biblio string.h par exemple).

Utilise int pour les entiers, et double pour les réels.
0
armasousou Messages postés 1270 Date d'inscription dimanche 16 août 2009 Statut Membre Dernière intervention 30 décembre 2016 83
7 nov. 2012 à 19:25
Pour être précis, char permet de faire "correspondre" le nombre qui lui est inclut (par exemple 65) en caractere correspondant à ce nombre dans la table asci (ici, A).

Si tu fais char secret='A';
La variable secret prend la valeur 65, le printf("%c", secret); affiche donc le caractere (%c) correspondant.

Tu peux bien faire int x=65;
printf("%c", x);
ca affichera aussi "A" :)

Ceux ne sont que des types de données, derrieres ya des paquet d'octets, ce qui compte c'est comment on les interprete ^^

Ici %c l'interprete comme un caractere (donc il va cherche dans la table asci), un %i (ou %d) vera la variable comme un entier, un %s pour une chaine de caractere (phrase).



Par ailleurs, les gens au dessus disent des betises, en aucun cas un unsigned int est codé sur 32 bit ou autre. Le char est codé sur 8 bits, ca c'est sur, le reste depend de la machine.
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
7 nov. 2012 à 19:30
"les gens au dessus disent des betises, en aucun cas un unsigned int est codé sur 32 bit ou autre"
Vu les valeurs numériques qu'a obtenu Jork, c'est bien du 32 bits qui est exécuté.
0
armasousou Messages postés 1270 Date d'inscription dimanche 16 août 2009 Statut Membre Dernière intervention 30 décembre 2016 83
7 nov. 2012 à 19:42
Ce n'est tout de même pas à généraliser.
0
Arrête de dire des bêtises KX !

Merci pour ton message armasousou, mais le but de ma question n'était pas de demander comment utiliser le type char, mais de comprendre ce qui se passait au niveau inférieur afin d'expliquer les résultats obtenu dans cet exemple bien précis :)
0