Transmission binaire

Voir le sujet précédent Voir le sujet suivant Aller en bas

Transmission binaire

Message  cirdan le Mer 3 Juin 2009 - 11:30

Bonjour, je fais référence à cette note : http://www.bien-programmer.fr/reseaux.htm#binaire

* Si je veux envoyer un entier signé, est-ce que ceci est portable, si les deux machines ont la même représentation des nombres signés (mais pas le même endianness) ? :

Transmission
Code:
signed long size = -256;
 
/* donnees 'taille' effectivement transmises */
unsigned char data[4];
 
data[0] = (size >> (3 * 8)) & 0xFF; /* MSB (3) en tete (0) */
data[1] = (size >> (2 * 8)) & 0xFF;
data[2] = (size >> (1 * 8)) & 0xFF;
data[3] = (size >> (0 * 8)) & 0xFF;

réception
Code:
signed long size = 0;
     
size |= (data[0] << (3 * 8)) ; /* MSB (3) en tete (0) */
size |= (data[1] << (2 * 8)) ;
size |= (data[2] << (1 * 8)) ;
size |= (data[3] << (0 * 8)) ;

La seule chose que j'ai changé, c'est le type de la variable size.

* Est-ce qu'il ne faut pas remplacer '8', par CHAR_BIT ?

* Si je veux envoyer un entier de 8 octets, imaginons sur ma machine le type unsigned long long.
Je vais avoir ce warning : 'left shift count >= width of type' pour les premiers décalages en réception :

Code:

unsigned long long size;

size |= (data[0] << (7 * 8)) ; /* warning */
size |= (data[1] << (6 * 8)) ; /* warning */
size |= (data[2] << (5 * 8)) ; /* warning */
size |= (data[3] << (4 * 8)) ; /* warning */
size |= (data[4] << (3 * 8)) ;
size |= (data[5] << (2 * 8)) ;
size |= (data[6] << (1 * 8)) ;
size |= (data[7] << (0 * 8)) ;

Ca me semble normal, le paramètre à gauche de '<<' est converti certainement en unsigned int (4 octets).

Est-ce que ceci est OK :

Code:

unsigned long long size;

size |= ((unsigned long long)data[0] << (7 * 8)) ;
size |= ((unsigned long long)data[1] << (6 * 8)) ;
size |= ((unsigned long long)data[2] << (5 * 8)) ;
size |= ((unsigned long long)data[3] << (4 * 8)) ;
size |= ((unsigned long long)data[0] << (3 * 8)) ;
size |= ((unsigned long long)data[1] << (2 * 8)) ;
size |= ((unsigned long long)data[2] << (1 * 8)) ;
size |= ((unsigned long long)data[3] << (0 * 8)) ;

J'ai fait le cast de partout bien que ce n'est pas la peine.

Et si j'ai un signé, cette fois je change que le type au début :

Code:
signed long long size;

size |= ((unsigned long long)data[0] << (7 * 8)) ;
size |= ((unsigned long long)data[1] << (6 * 8)) ;
size |= ((unsigned long long)data[2] << (5 * 8)) ;
size |= ((unsigned long long)data[3] << (4 * 8)) ;
size |= ((unsigned long long)data[0] << (3 * 8)) ;
size |= ((unsigned long long)data[1] << (2 * 8)) ;
size |= ((unsigned long long)data[2] << (1 * 8)) ;
size |= ((unsigned long long)data[3] << (0 * 8)) ;

cirdan

Messages : 5
Date d'inscription : 20/05/2009

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Transmission binaire

Message  -ed- le Mer 3 Juin 2009 - 13:45

cirdan a écrit:Bonjour, je fais référence à cette note : http://www.bien-programmer.fr/reseaux.htm#binaire

* Si je veux envoyer un entier signé, est-ce que ceci est portable, si les deux machines ont la même représentation des nombres signés (mais pas le même endianness) ? :
Oui, c'est le but ! Le principe est de convertir la représentation dans un format indépendant de la machine. Ce format est respecte la convention "réseau" qui est "poids fort en tête". Il doit aussi impérativement être d'une taille fixe (2, 3, 4, 6, 8 octets etc.). Tout cela est conventionnel.
Transmission
Code:
signed long size = -256;
 
/* donnees 'taille' effectivement transmises */
unsigned char data[4];
 
data[0] = (size >> (3 * 8)) & 0xFF; /* MSB (3) en tete (0) */
data[1] = (size >> (2 * 8)) & 0xFF;
data[2] = (size >> (1 * 8)) & 0xFF;
data[3] = (size >> (0 * 8)) & 0xFF;

réception
Code:
signed long size = 0;
     
size |= (data[0] << (3 * 8)) ; /* MSB (3) en tete (0) */
size |= (data[1] << (2 * 8)) ;
size |= (data[2] << (1 * 8)) ;
size |= (data[3] << (0 * 8)) ;

La seule chose que j'ai changé, c'est le type de la variable size.
Alors ici, la transmission se fait sur 4 octets. Les valeurs transmises doivent être représentables par une combinaison de bits comprise entre entre 0 et 0xFFFFFFFF.
* Est-ce qu'il ne faut pas remplacer '8', par CHAR_BIT ?
Surtout pas. Il s'agit d'octets (format réseau) qui n'ont rien à voir avec les char de l'implémentation (c'est ça l'indépendance).

* Si je veux envoyer un entier de 8 octets, imaginons sur ma machine le type unsigned long long.
Je vais avoir ce warning : 'left shift count >= width of type' pour les premiers décalages en réception :

Code:

unsigned long long size;

size |= (data[0] << (7 * 8)) ; /* warning */
size |= (data[1] << (6 * 8)) ; /* warning */
size |= (data[2] << (5 * 8)) ; /* warning */
size |= (data[3] << (4 * 8)) ; /* warning */
size |= (data[4] << (3 * 8)) ;
size |= (data[5] << (2 * 8)) ;
size |= (data[6] << (1 * 8)) ;
size |= (data[7] << (0 * 8)) ;

Ca me semble normal, le paramètre à gauche de '<<' est converti certainement en unsigned int (4 octets).

Exact. Il faut forcer la conversion en ull (unsigned long long) :
Code:

size |= (data[0] << (7 * 8ull)) ;
etc.
Est-ce que ceci est OK :
Non. J'ai indiqué comment faire. D'ailleurs en toute rigueur, pour transmettre en 32-bit, on devrait faire :
Code:
signed long size = 0;

size |= (data[0] << (3 * 8ul)) ; /* MSB (3) en tete (0) */
size |= (data[1] << (2 * 8ul)) ;
size |= (data[2] << (1 * 8ul)) ;
size |= (data[3] << (0 * 8ul)) ;

(Obligatoire sur un compilateur 16 bit.)

_________________
C is a sharp tool !

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Re: Transmission binaire

Message  cirdan le Mer 3 Juin 2009 - 15:59

-ed- a écrit:Il faut forcer la conversion en ull (unsigned long long) :
Code:

size |= (data[0] << (7 * 8ull)) ;
etc.
Est-ce que ceci est OK :
Non. J'ai indiqué comment faire.

Pourquoi c'est pas bon ?

Alors ici, la transmission se fait sur 4 octets. Les valeurs transmises doivent être représentables par une combinaison de bits comprise entre entre 0 et 0xFFFFFFFF.

Mais alors, c'est pas portable ?
Puisque si sizeof(long) == 8, dès que j'aurais un nombre négatif, le bit de poids le plus fort sera à 1, et la représentation binaire ne sera pas comprise entre 0 et 0xFFFFFFFF.

Non ?

cirdan

Messages : 5
Date d'inscription : 20/05/2009

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Transmission binaire

Message  cirdan le Mer 3 Juin 2009 - 16:31

Code:
unsigned long long number;

number = 0xFF << 24ull;

printf("%llx\n", number);

m'affiche : ffffffffff000000

mais

Code:
unsigned long long number;

number = ((unsigned long long)0xFF) << 24ull;

printf("%llx\n", number);

m'affiche : ff000000

cirdan

Messages : 5
Date d'inscription : 20/05/2009

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Transmission binaire

Message  -ed- le Mer 3 Juin 2009 - 17:26

Avant toute chose, il faut savoir si ton système de développement est à jour (certaines versions de Windows ne supportent pas "%llx").

Chez moi (Vista SP1 / Code::Blocks 8.02) , ce code :
Code:
#include <stdio.h>

int main (void)
{
  unsigned long long x = 0xFF;

  printf ("x = %016llX\n", x << (8 * 0ull));
  printf ("x = %016llX\n", x << (8 * 1ull));
  printf ("x = %016llX\n", x << (8 * 2ull));
  printf ("x = %016llX\n", x << (8 * 3ull));
  printf ("x = %016llX\n", x << (8 * 4ull));
  printf ("x = %016llX\n", x << (8 * 5ull));
  printf ("x = %016llX\n", x << (8 * 6ull));
  printf ("x = %016llX\n", x << (8 * 7ull));


  return 0;
}
affiche
Code:

x = 00000000000000FF
x = 000000000000FF00
x = 0000000000FF0000
x = 00000000FF000000
x = 000000FF00000000
x = 0000FF0000000000
x = 00FF000000000000
x = FF00000000000000

Process returned 0 (0x0)  execution time : 0.021 s
Press any key to continue.

_________________
C is a sharp tool !

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Re: Transmission binaire

Message  -ed- le Mer 3 Juin 2009 - 17:36

cirdan a écrit:
Code:
unsigned long long number;

number = 0xFF << 24ull;

printf("%llx\n", number);

m'affiche : ffffffffff000000
Normal. 0xFF est un int. Il est promu en long long...

Ceci fonctionne :
Code:

#include <stdio.h>

int main (void)
{
  unsigned long long number;

  number = 0xFFu << 24ull;

  printf("%llx\n", number);

  return 0;
}

_________________
C is a sharp tool !

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Re: Transmission binaire

Message  Contenu sponsorisé Aujourd'hui à 21:19


Contenu sponsorisé


Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum