Codage des entiers

Résolu
Aurel184 Messages postés 21 Date d'inscription dimanche 14 mars 2004 Statut Membre Dernière intervention 9 juin 2010 - 23 févr. 2007 à 12:13
Aurel184 Messages postés 21 Date d'inscription dimanche 14 mars 2004 Statut Membre Dernière intervention 9 juin 2010 - 23 févr. 2007 à 14:11
Bonjour,

je développe une interface en Delphi permettant de contrôler par réseau ou port série des vidéoprojecteurs professionnels. Quand j'envoi une commande, le projecteur me répond. C'est au moment de la gestion de la réponse que se trouve mon problème.

Le projecteur m'envoie une chaîne binaire de 33 octets. Je stocke cette chaîne dans une structure :

TBinaire = record
    _Response : byte; // 1 octet
    _Header : array [0..4] of byte; // 5 octets
    _CRC : array [0..1] of byte; // 2 octets
    _OperationType : byte; //1 : SET, 2 : GET, 3 : Increment, 4 : Decrement 5 : execute, 7 : Descriptor
    _OperationNumber : array [0..1] of byte; // 2 octets
    _OperationValid : byte; //1 octet, 0 ->error, 1 ->good
    _NotUsed : array [0..4] of byte; // 5 octets
    _OperationValue : array [0..1] of byte; // 2 octets
    _OparationValueNotUsed : array [0..1] of byte; // 2 octets
    _LowerLimit : array [0..3] of byte; // 4 octets
    _UpperLimit : array [0..3] of byte; // 4 octets
    _Increment : array [0..3] of byte; // 4 octets
  end;

La fonction SizeOf() renvoie bien 33 octets comme taille de structure. Comme l'aide Delphi dit que le type Word est en entier non signé de 16bits et le longWord un entier non signé de 32 bits, j'ai modifié ma structure :

TBinaire = record
    _Response : byte; // 1 octet
    _Header : array [0..4] of byte; // 5 octets
    _CRC : Word; // 2 octets
    _OperationType : byte; //1 : SET, 2 : GET, 3 : Increment, 4 : Decrement 5 : execute, 7 : Descriptor
    _OperationNumber : Word; // 2 octets
    _OperationValid : byte; //1 octet, 0 ->error, 1 ->good
    _NotUsed : array [0..4] of byte; // 5 octets
    _OperationValue : Word; // 2 octets
    _OparationValueNotUsed : Word; // 2 octets
    _LowerLimit : Longword; // 4 octets
    _UpperLimit : Longword; // 4 octets
    _Increment : Longword; // 4 octets
  end;

Et là SizeOf() renvoie 36 octets comme taille de structure. Et les données sont décallées et donc non traitable. Ma question : Est ce que j'aurait raté quelque chose sur le codage des Word ? Où sont les 3 octets qui sont apparus dans la deuxième forme de ma structure ? Merci d'aclairer ma lanterne.

3 réponses

florenth Messages postés 1023 Date d'inscription dimanche 1 août 2004 Statut Membre Dernière intervention 17 août 2008 2
23 févr. 2007 à 13:04
Salut,

Ahah, en voila une question qu'elle est intéréssante !
En fait, Delphi aligne les données des structures "record" en fonction de la valeur de la directive de compilation {$A}.

Par défaut, en mode {$A+}, les différents champs de ta structure qui font plus d'un octet sont alignés sur les frontières des quadruples mots.
Concrètement, cela signifie que Delphi ajoute des zéros entre tes différents champs pour optimiser l'accès mémoire.
Dans ta première version, comme tu n'utilises que des Byte, rien ne dépasse un octet en taille. Mais dans la deuxième, l'utilisation de Word et Longword fait que Delphi va aligner tes champs, d'où le problème que tu rencontres.

Dans certains cas, comme le tien, la taille de l'entegistrement est importante et doit être fixe.
Pour pallier à ce problème, il faut le signaler à Delphi en utilisant le modificateur "packed" devant la déclaration.

Ce qui donne pour ton type :
-----------------------------
TBinaire = packed record // <== Ajout du mot "packed"
Response : Byte;
Header : array [0..4] of Byte;
CRC : Word;
OperationType : Byte;
OperationNumber : Word;
OperationValid : Byte;
NotUsed : array [0..4] of Byte;
OperationValue : Word;
OparationValueNotUsed : Word;
LowerLimit : Cardinal;
UpperLimit : Cardinal;
Increment : Cardinal;
end;
-----------------------------

Et là, ton type fait bien 33 octets comme demandé...
Un conseil en plus :
- Evite les underscore dans les noms de champs, c'est inutile et plus dur à lire.
- Le type Cardinal est un type natif qui correspond au type Longword donc tu peux tout remplacer tes Longword en Cardinal (de même, les HRESULT sont en fait des Integer, etc...)

Bonne prog'
Florent
3
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 48
23 févr. 2007 à 13:15
Salut,

arghh ... Florenth tu m'as pris de vitesse

 
@+
Cirec

<hr size="2" />
0
Aurel184 Messages postés 21 Date d'inscription dimanche 14 mars 2004 Statut Membre Dernière intervention 9 juin 2010 1
23 févr. 2007 à 14:11
Merci beaucoup !
Je n'aurais jamais pensé que ça vienne d'une optimisation de compilation. J'aurais pu chercher encore longtemps

Aurel
0