Forum Programmation.c Lecture de fichier binaire

Posté par  (site web personnel) .
Étiquettes : aucune
0
2
fév.
2007
Bonjour!

Je suis en train de faire un convertisseur d'un format de fichier binaire vers ascii, et je dois lire un float codé sur 2 bytes.

J'ai donc le code suivant:

size=2;
ptr=(short int *)malloc(size);
fread(ptr,(size_t)size,1,data_file);
printf("%02X ",*((short int *)ptr));
free(ptr);

Avec prt un pointeur sur void.

Lorsque j'édite mon fichier avec khexedit, cela commence comme ceci:

47d0 63e8 6fa0 43e8 45dc 6fa0 ...


Et mon programme m'affiche ces mêmes lignes de la façon suivante:

FFFFD047 FFFFE863 FFFFA06F FFFFE843 FFFFDC45 FFFFA06F ...


Evidement, lorsque j'essaye d'utiliser ce que je vient de lire pour calculer mon float dans la représentation du fichier binaire, je calcule nimporte quoi...

Donc, comment cela se fait-il que mes deux octets soient inversés lors de ma lecture par rapport a khexedit? Et d'ou viennent des FFFF??

Merci pour toute aide pour éclairer ma lanterne!
Mathias
  • # un petit endien .. nagawika ...

    Posté par  . Évalué à 2.

    C' est quoi la taille d'un short int sur ta plate-forme ?

    Pour l'inversion, c' est probablement dû au big endian/ little
    endian (prise en compte d'abord des octects de poids faible ou de poid fort). Utilise les routines qui permettent de convertir en format "réseau" (man byteorder pour plus d'infos)
    • [^] # Re: un petit endien .. nagawika ...

      Posté par  (site web personnel) . Évalué à 2.

      un short int, c'est 2 bytes...

      Mais effectivement, un coup de byteorder et ça repart ! (et les FFFF de tête n'y sont plus).

      Merci!

      Mathias
      • [^] # Re: un petit endien .. nagawika ...

        Posté par  (site web personnel) . Évalué à 2.

        Tu as quand même un problème ici :
        printf("%02X ",*((short int *)ptr));

        %X c'est destiné à afficher, sous forme hexa, des entiers non signés, et là tu donne un entier court signé.

        http://www.opengroup.org/onlinepubs/007908799/xsh/fprintf.ht(...)

        Il faudrais que tu passes d'entier court en entier en le spécifiant. Par exemple:
        short v ;
        assert(sizeof(v)==2) ; // petit controle au cas ou
        fread(&v,sizeof(v),1,data_file);
        printf("%02X ",(unsigned int)v);

        Je ne sais plus comment il joue avec le bit de poids fort lorsqu'il passe d'un signé à un non-signé plus long, mais tu peux éventuellement forcer les bits qui ne te concernent pas à zéro: unsigned int uv = (unsigned int)0x00FFFF & (unsigned int)v ;

        Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN

        • [^] # Re: un petit endien .. nagawika ...

          Posté par  . Évalué à 1.

          Je ne sais plus comment il joue avec le bit de poids fort lorsqu'il passe d'un signé à un non-signé plus long,

          En C, les conversions se font toujours en essayant de préserver la valeur. Si la valeur de départ "tient" dans le type d'arrivée, alors elle est conservée telle quelle. Sinon, ça dépend... Dans le cas d'une conversion vers un type non signé, la conversion se fait modulo (le nombre maximal représentable par ce type) + 1 (i.e. UINT_MAX +1 dans le cas d'unsigned int).

          Donc, si la valeur de v est négative, la conversion en unsigned int se fera avec un changement de valeur modulo UINT_MAX +1. Sinon, comme on a par ailleurs SHORT_MAX <= INT_MAX <= UINT_MAX, la valeur après conversion sera identique. Pas besoin de jouer avec les opérateurs binaires...

          En passant, il sert à quoi ton assert ?
  • # Commentaires

    Posté par  . Évalué à 1.

    size=2;
    ptr=(short int *)malloc(size);
    • Le cast de la valeur de retour de *alloc est inutile et peut même cacher l'oubli d'inclusion de stdlib.h. A éviter.
    • Tu n'as pas vérifié que ptr n'est pas nul...
    fread(ptr,(size_t)size,1,data_file);
    • Le cast en size_t est inutile, la conversion se faisant implicitement lors de l'appel de fread.
    • Tu as oublié de vérifier la valeur de retour de fread, donc tu ne sais pas si tu as effectivement lu ce que tu voulais, ou non. Il a pu y avoir une erreur d'I/O...
    • L'utilisation d'une valeur "size" est douteuse si ton code ne fait que ça... Evite, car ça risque d'être source de bugs (pas portable, valeur modifée en cours de programme...).
    printf("%02X ",*((short int *)ptr));
    Comme dit par ailleurs, c'est horrible.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.