Format specifies type 'unsigned char' but ... has type int

Résolu
leoliom Messages postés 164 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 14 janvier 2023 - Modifié le 6 janv. 2023 à 15:27
leoliom Messages postés 164 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 14 janvier 2023 - 6 janv. 2023 à 20:22

Bonjour,

J'ai un soucis avec le code suivant :

#include <stdio.h>

int main(){   
   int a = 5 ;
   int b = 1000 ; // 0x3e8
   printf("0x%02hhx\n", a); 
   printf("0x%02hhx\n", b); 
   return 0;
}

Ça me renvoie toujours :

warning: format specifies type 'unsigned char' but the argument has type 'int' [-Wformat]
   printf ( "0x%02hhx\n" ,a) ; 
               ~~~~~~     ^
               %02x

warning: format specifies type 'unsigned char' but the argument has type 'int' [-Wformat]
   printf ( "0x%02hhx\n" , b ) ; 
               ~~~~~~      ^
               %02x

Mais ça me renvoie bien les résultats que je veux avoir:

0x05
0xe8

Pourquoi ces warnings ? Le code que j'ai écrit est-il faux? Normalement je peux utiliser %hhx même si c'est pour afficher 1 octet (car 1 char = 1octet) on peut l'utiliser aussi pour les int non ?
Windows / Chrome 108.0.0.0

A voir également:

10 réponses

Pourquoi ne pas essayer: "0x%02x\n" ?

Le 0 dit que tu remplis avec des 0, le 2 dit que ton champs doit avoir au moins 2 caractères.

0
leoliom Messages postés 164 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 14 janvier 2023 2
Modifié le 6 janv. 2023 à 15:25

Le problème, c'est que ça m'affiche:

0x05
0x3e8

... or mon but est d'avoir :

0x05
0xe8

Je ne veux que les 2 premiers octets

Et d'ailleurs je sais pas pourquoi %02x ne m'affiche pas que les 2 premiers octets c'est comme si le fait que j'ai spécifié 2 ne servait à rien

0
PierrotLeFou
27 déc. 2022 à 17:55

J'ai bien dit "au moins" deux caractères.
Si tu ne veux que le dernier octet, tu peux afficher a % 256 ou a & 0xff

0
leoliom Messages postés 164 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 14 janvier 2023 2
Modifié le 6 janv. 2023 à 15:27

Si j'écris ceci ça m'affiche bien le résultat que je veux :

#include <stdio.h>

int main() {
   int a = 5;
   int b = 1000; // 0x3e8
   printf( "0x%02x\n", a % 256); 
   printf( "0x%02x\n", b % 256); 
   return 0;
}

Vous vouliez dire si je veux exclure le dernier octet, je dois écrire % 256 ,car si vous ne vous êtes pas trompé dans vos mots, cela ne m'affiche pas spécifiquement le dernier octet (3)

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question

Je pense que tu te méprends sur le terme "octet",
Le nombre décimal 24 s'écrit en binaire 0001 1000
Ça entre dans un octet mais c'est représenté par 2 caractères en hexadécimal: 0x18

  • Si je veux afficher le 4, j'affiche a % 10, si je veux afficher le 2, je fais a / 10 % 10 en format %d
  • Si je veux afficher le 8, je fais a % 16. Si je veux afficher le 1, je fais a / 16 % 16 en format %x
0
leoliom Messages postés 164 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 14 janvier 2023 2
Modifié le 6 janv. 2023 à 15:30

Ok, je vois c'est une autre façon de faire sans utiliser %x. Oui, j'ai confondu octet avec les 4 bit d'un nombre

Par exemple si j'ai :

#include <stdio.h>

int main() {
   int a = 12345678; // 0xbc614e
   printf("%x\n", a / 16 % 16);
   return 0;
}

Pourquoi ça n'affiche pas le le bit de poids fort a savoir b?

a%16%16 ne marche que pour des nombres à 2 chiffres

Et aussi est-ce une bonne pratique de convertir un type comme par exemple char en un type plus grand à savoir par exemple float,int etc. ?

Aussi, est-ce une bonne pratique de convertir un type grand par exemple long en un type plus petit a savoir par exemple char ?

Car je voudrais savoir si c'est exact de faire ceci:

int main(){
   long a = 12345678;
   printf("%hhx\n", (char) a);

   char b = 123;
   printf("%hx\n", (short) b);
   return 0;
}
0

Tu essaies beaucoup de choses. C'est OK pour expérimenter. Mais que veux-tu faire exactement?

  • Quand tu castes un grand nombre dans un petit, tu perds les chiffres les plus significatifs.
  • Si tu fais le contraire, ce n'est pas grave, mais tu perds en mémoire.

Il faut faire la différence entre la valeur interne d'un nombre et son affichage (ou sa représentation en caractères).

0
leoliom Messages postés 164 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 14 janvier 2023 2
Modifié le 6 janv. 2023 à 15:51

En fait, je veux juste éviter que les warnings s'affichent, car en faisant ceci, il n'y a plus de warning :

#include <stdio.h>

int main() {
   int a = 5 ;
   int b = 1000 ; // 0x3e8
   printf("0x%02hhx\n", (char) a); 
   printf("0x%02hhx\n", (short) b); 
   return 0;
}

Ok, je vois pour les conversions et les pertes d'infos, merci.

0
mamiemando Messages postés 32079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 30 janvier 2023 7 536
Modifié le 6 janv. 2023 à 15:51

Bonjour,

Concernant ton message #8, si j'ai bien compris le but est d'afficher l'octet de poids faible sous forme héxadécimale.

Faire un cast vers un type qui fait un octet fait le travail, même si je trouve ça un peu cavalier personnellement. En effet il y a de bonne chance que l'opération de cast sélectionne les octets des poids faible (ici l'octet de poids faible) pour réaliser le cast. Ensuite il faut bien voir que le cast fait une partie du travail, mais la chaîne de formatage fait le reste, et selon la valeur assignée à l'entier tu utilises tantôt un (char), tantôt un (short).

Bref, ce que je ferais plutôt à ta place, c'est appliquer le masque & 0xff qui va sélectionner le dernier octet, puis afficher la valeur ainsi obtenue.

#include <stdio.h>

int main() {
  int a = 5;
  int b = 1000;
  printf("0x%02x\n", a & 0xff) ;
  printf("0x%02x\n", b & 0xff) ;
  return 0;
}

Pour des types plus grands que des int, tu ne peux pas appliquer un masque directement, donc il faut présenter la donnée (par exemple le float) comme un tableau indexé octet par octet (genre un unsigned char * ou de manière plus parlante un uint8_t *), extraire le bon octet, et l'afficher.

#include <stdio.h>
#include <stdint.h>

int main() {
   float a = 5;
   float b = 1000;
   printf("0x%02x\n", ((uint8_t *) &a)[sizeof(a) - 1]);
   printf("0x%02x\n", ((uint8_t *) &b)[sizeof(b) - 1]);
   return 0;
}

Bonne chance

0
leoliom Messages postés 164 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 14 janvier 2023 2
6 janv. 2023 à 20:22

Merci beaucoup pour ces éclaircissements!!!

0