Bien programmer en langage C
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.
-20%
Le deal à ne pas rater :
-20% Récupérateur à eau mural 300 litres (Anthracite)
79 € 99 €
Voir le deal

Transmission binaire

2 participants

Aller en bas

Transmission binaire Empty Transmission binaire

Message  cirdan 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

Revenir en haut Aller en bas

Transmission binaire Empty Re: Transmission binaire

Message  -ed- 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.)
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

Transmission binaire Empty Re: Transmission binaire

Message  cirdan 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

Revenir en haut Aller en bas

Transmission binaire Empty Re: Transmission binaire

Message  cirdan 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

Revenir en haut Aller en bas

Transmission binaire Empty Re: Transmission binaire

Message  -ed- 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.
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

Transmission binaire Empty Re: Transmission binaire

Message  -ed- 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;
}
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

Transmission binaire Empty Re: Transmission binaire

Message  Contenu sponsorisé


Contenu sponsorisé


Revenir en haut Aller en bas

Revenir en haut


 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
Ne ratez plus aucun deal !
Abonnez-vous pour recevoir par notification une sélection des meilleurs deals chaque jour.
IgnorerAutoriser