Salut,
Le type bytes d'existe pas en C et tu peux utiliser unsigned char. Voilà comment on peux procéder pour convertir un tableau de 4 unsigned char en un entier:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <stdio.h>
#include <stdlib.h>
int main(void)
{
unsigned char tab[4] = {0, 1}; /* correspond au mot 0x100 i.e 256 */
int nombre;
nombre = *(int *)tab; /* Convertion du tableau en un entier de type int */
printf("Le nombre obtenu est %d\n", nombre);
return EXIT_SUCCESS;
} |
Cette méthode n'est pas portable et fonctionne sur un système Little Endian. La méthode que tu propose a l'avantage d'être portable, dans la mesure ou un int est représenté sur au moins 32 bits (int est toujours représenté avec 32 bits en Java. La norme C, malheureusement, garantit que la valeur max d'un int est 32767). Pour la suite, je suppose qu'un entier de type int est représenté sur 32 bits (Au besoin, on peut utilisé le type long).
En ce qui concerne la syntaxe que tu as donné, mettons que buffer[1] contient la valeur 16 i.e 00010000 en binaire i.e 0x10:
1 2
| int nombre = 0;
nombre = (buffer[1] & 0xff) << 8; |
nombre reçoit la valeur 0x100. Si on décompose ce qui se passe:
- 0xff est une constante entière de type int i.e 0x000000ff
- buffer[1] est converti en entier 32bits i.e. 0x00000010
- Les 3 octets de poids fort de cette valeur sont mis à 0 (ici, 0xFF joue le role de masque). On obtient 0x00000010
- On décale le pattern de bits de 8 position vers la gauche et on obtient 0x100
Maintenant, si on prend:
1 2
| int nombre = 0;
nombre = ((buffer[0] & 0xFF) << 8) | (buffer[0] & 0xff); |
Si on suppose que buffer[0] contient la valeur 0xA0 codée sur 8 bits non signés. L'expression ci-dessus est équivalente à:
1 2
| int nombre = 0;
nombre = 0x00000100 | 0x000000A0; |
Et nombre prend la valeur 0x000001A0. L'opérateur | correspond à un ET bit à bit.
Maintenant, il n'y a pas de types non signés en Java, ce qui oblige d'écrire:
int nombre = (buffer[0] & 0xFF) | ((buffer[1] & 0xFF) << 8) | ((buffer[2] & 0xFF) << 16) | ((buffer[3] & 0xFF) << 24);
En effet, lorsqu'on transforme un octet signé valant 0xA0 en entier 32 bits:
1 2 3
| int nombre = 0;
signed char un_byte = 0xA0;
nombre = un_byte; /* nombre prend la valeur 0xFFFFFFA0 */ |
Ainsi, l'utilisation du masque devient évidente:
nombre = un_byte & 0xFF; /* nombre prend la valeur 0x000000A0 */
En conclusion, il est possible d'alléger la syntaxe utilisée par Java en C, en déclarant buffer comme un tableau de unsigned char:
nombre = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
Thierry
Partager